FastCheck Forum Index FastCheck
Get notified when you receive new emails!
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Second test version of FastServices API
Goto page 1, 2, 3, 4  Next
 
Post new topic   Reply to topic    FastCheck Forum Index -> FastServices
View previous topic :: View next topic  
Author Message
Jeremy Howard
The "e" in e-mail


Joined: 09 Apr 2002
Posts: 325
Location: Melbourne

PostPosted: Fri Aug 29, 2003 4:03 am    Post subject: Second test version of FastServices API Reply with quote

Okay folks, good news, we've now changed the FastServices protocol so it should be much more easy to work with languages other than Perl, including Delphi, and .Net.

First, grab the latest Perl test script from here:
http://jhoward.fastmail.fm/fastcheck/testsoapfolders.pl

Now, create a directory called "SOAP" wherever you downloaded to the test script to, and then download the following module into that directory:
http://jhoward.fastmail.fm/fastcheck/MessagingEngine.pm

Next, open up a command prompt or terminal in the directory where you placed the Perl test script, and type the following command:
Code:
perl -w scripts/fmtest/testsoapfolders.pl www.fastmail.fm username password

You will see lots of SOAP communication start appearing on your screen, to help you with your debugging and understanding of the protocol. To turn this off, find the line which says "+trace => [qw(all -transport)]," in MessagingEngine.pm, and add a hash symbol (#) before it to comment it out.

I will now explain what each part of the SOAP communication means by showing the body of each request and response:
Code:
POST http://www.fastmail.fm/SOAP/

<namesp1:CreateSession xmlns:namesp1="http://www.fastmail.fm/SOAP/MessagingEngine">
      <UserName xsi:type="xsd:string">testuser</UserName>
</namesp1:CreateSession>

<SOAP-ENV:Fault>
      <faultcode xsi:type="xsd:string"
      >SOAP-ENV:Client.Proxy</faultcode>
      <faultstring xsi:type="xsd:string"
      >Wrong server; please change to the correct endpoint for this user</faultstring>
      <detail xsi:type="xsd:string"
      >Wrong server specified; User: testuser; Required endpoint: http://www.fastmail.fm/SOAP2/; ServerName: 2; HostNum: 1</detail>
      <faultactor xsi:type="xsd:string"
      >http://www.fastmail.fm/SOAP2/</faultactor>
</SOAP-ENV:Fault>
This shows the code to create a session, which takes a single string parameter, of the username to create a session for. As you can see, in this case we used the wrong endpoint for this user. When you use FastServices, you must always check for this Fault, and change to the new endpoint requested. The " Faultactor" contains the new endpoint required. You should then save this value, and use it in the future for this username, since it will then make creating a session much faster.
Code:
POST http://www.fastmail.fm/SOAP2/

<SOAP-ENV:Body>
    <namesp2:CreateSession xmlns:namesp2="http://www.fastmail.fm/SOAP/MessagingEngine"
    >
      <UserName xsi:type="xsd:string"
      >testuser</UserName>
</namesp2:CreateSession>

<namesp1:CreateSessionResponse xmlns:namesp1="http://www.fastmail.fm/SOAP/MessagingEngine">
      <SessionStr xsi:type="xsd:string"
      >301aca0d939ce71cc610/2e96aab9/35e341ae</SessionStr>
      <OneTime xsi:type="xsd:string"
      >6d4c4b9d26297e79</OneTime>
      <Success xsi:type="xsd:int"
      >1</Success>
</namesp1:CreateSessionResponse>

We have now repeated to the call, changing only the endpoint in the post request. We have now been given a session string, and a challenge. From now on, every function that we call will return these two things as the first two parameters. Any additional return values will come after these two parameters; in this case there is a single return value indicating success or failure.

Code:
<namesp4:URL_CreateURL xmlns:namesp4="http://www.fastmail.fm/SOAP/MessagingEngine">
      <SessionStr xsi:type="xsd:string"
      >301aca0d939ce71cc610/2e96aab9/35e341ae</SessionStr>
      <OneTimeEnc xsi:type="xsd:string"
      >OTgQ7byRXfx5/5L4DDEJag</OneTimeEnc>
      <c-gensym12 xsi:type="xsd:string"
      >Compose</c-gensym12>
</namesp4:URL_CreateURL>

<namesp1:URL_CreateURLResponse xmlns:namesp1="http://www.fastmail.fm/SOAP/MessagingEngine">
      <SessionStr xsi:type="xsd:string"
      >301aca0d939ce71cc610/2e96aab9/35e341ae</SessionStr>
      <OneTime xsi:type="xsd:string"
      >4db3051c6bb1008b</OneTime>
      <HREF xsi:type="xsd:string"
      >
http://www.fastmail.fm/mail2/?Ust=2e96aab9!35e341ae;Uid=301aca0d939ce71cc610!1062127348;MSignal=MC-Service@0
</HREF>
</namesp1:URL_CreateURLResponse>
Above you see us calling our first API function. The first parameter must be the session string which was returned by CreateSession. The second parameter is the challenge that we received earlier, concatenated with a ":", concatenated with the user's password, which is then encrypted with MD5, and encoded with Base64. The Perl code which does this is:
Code:
md5_base64("$Self->{OneTime}:$OTPassword")
when you have ported this code snippet to your preferred language, please post it here.

After these two parameters, we pass any parameters that are required by the API function. The URL_CreateURL function takes one parameter, which is a string, showing the screen which a URL is required for.

As you can see, in the response we get the same two parameters that we always receive, to allow us to construct our next API call, followed by the actual return value or values from this API function. In this case, we get the URL that we requested in the third parameter. This API call returns a URL for an already open session, so going to this URL in a web browser is very fast indeed (no authentication or redirects required).

Finally, I will show one more example.
Code:
<namesp3:AccountInfo_GetFolderList xmlns:namesp3="http://www.fastmail.fm/SOAP/MessagingEngine">
      <SessionStr xsi:type="xsd:string"
      >301aca0d939ce71cc610/2e96aab9/35e341ae</SessionStr>
      <OneTimeEnc xsi:type="xsd:string"
      >S9TZOcu4zfu05oLR1XDSkA</OneTimeEnc>
</namesp3:AccountInfo_GetFolderList>

<namesp1:AccountInfo_GetFolderListResponse xmlns:namesp1="http://www.fastmail.fm/SOAP/MessagingEngine">
      <SessionStr xsi:type="xsd:string"
      >301aca0d939ce71cc610/2e96aab9/35e341ae</SessionStr>
      <OneTime xsi:type="xsd:string"
      >ec0b9194f2170e56</OneTime>
      <FolderList xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="namesp2:SOAPStruct[4]">
        <item xsi:type="namesp2:SOAPStruct">
          <MessageCount xsi:type="xsd:int"
          >6</MessageCount>
          <NoSelect xsi:type="xsd:int"
          >0</NoSelect>
          <UnreadCount xsi:type="xsd:int"
          >5</UnreadCount>
          <FolderName xsi:type="xsd:string"
          >Inbox</FolderName>
          <FolderId xsi:type="xsd:int"
          >1121269</FolderId>
        </item>
<...>
      </FolderList>
</namesp1:AccountInfo_GetFolderListResponse>
the AccountInfo_GetFolderList does not take any parameters, so only the usual session string and encoded password are passed to the function.

The only tricky bit here is in the return value. The return value uses a hash (known as a hashtable, map, dictionary, and various other things in other languages), for which there is no standard serialisation in SOAP. We are using the SOAPStruct type from the "http://xml.apache.org/xml-soap" namespace, which may not be supported in all languages. If you have better ideas for how to serialise these types of structure, in order to simplify interoperability, please let us know.

Once we have this basic framework ported to one or more other languages, we will begin expanding the API to provide rich functionality. Please do post here if you have any questions or comments. Once you have something in your preferred language, post a URL to your code, so we can all check it out! Smile
Back to top
View user's profile Send private message Visit poster's website
rthomas



Joined: 25 Aug 2003
Posts: 11
Location: France, Lille

PostPosted: Fri Aug 29, 2003 7:58 am    Post subject: Stiil have problem Reply with quote

Back to top
View user's profile Send private message Send e-mail Visit poster's website
Kander



Joined: 22 Apr 2003
Posts: 31

PostPosted: Fri Aug 29, 2003 8:45 am    Post subject: Re: Second test version of FastServices API Reply with quote

[quote="Jeremy Howard"]The Perl code which does this is:
Code:
md5_base64("$Self->{OneTime}:$OTPassword")


PHP:


Not sure if/how this gives the same result as the Perl code... I don't know anything about Perl. Could someone run the perl script with inputs $Self->(OneTime) being set as Foobar and $OTPassword being set as 'mypassword' to compare results?

I assume OneTime is a property of the object $Self? and $OTPassword is just a variable?

Code:

base64_encode(md5($Self->OneTime.":".$OTPassword));


My output is: YzhlNzk3NzlhMWJjMzE4YTRhMGZlN2NiYjI5NDdhZGU=

Note: Not sure if Jeremy's Perl does the MD5 or the Base64 first, so just in case it's the other way around:
Code:

md5(base64_encode($Self->OneTime.":".$OTPassword));


Second output: c3cd5272cb722f2d9d08e52ea777c444

I hope this helps anyone a bit...
--K
Back to top
View user's profile Send private message
eric_thiebaut
Site Admin


Joined: 07 Apr 2002
Posts: 1523
Location: Sydney, Australia

PostPosted: Fri Aug 29, 2003 9:43 am    Post subject: Much better! Reply with quote

Yep, much easier!

I can now send the first CreateSession request, get the redirection URL and send the second request, which succeeds!
The only problem: for the moment, I can't get the results. But I'm almost there, so I reckon it shouldn't take me too long! Smile

Eric
Back to top
View user's profile Send private message Send e-mail Visit poster's website
eric_thiebaut
Site Admin


Joined: 07 Apr 2002
Posts: 1523
Location: Sydney, Australia

PostPosted: Fri Aug 29, 2003 10:42 am    Post subject: Reply with quote

Yeah baby, Yeah! Got it!

The problem was because perl doesn't return fully qualified attributes. So by removing 'elementFormDefault="qualified"' it all works!

So here's the wsdl:
Code:
<?xml version="1.0" encoding="utf-8"?>
<definitions
   xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
   xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
   xmlns:s0="http://www.fastmail.fm/SOAP/MessagingEngine"
   xmlns:soapenc="http://schemas.xmlsoap.org/SOAP/encoding/"
   xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/"
   xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
   xmlns:xsd="http://www.w3.org/2001/XMLSchema"
   xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
   targetNamespace="http://www.fastmail.fm/SOAP/MessagingEngine"
   xmlns="http://schemas.xmlsoap.org/wsdl/">

  <types>
    <xsd:schema targetNamespace="http://www.fastmail.fm/SOAP/MessagingEngine">

      <xsd:element name="CreateSession">
        <xsd:complexType>
          <xsd:sequence>
            <xsd:element minOccurs="1" maxOccurs="1" name="UserName" type="xsd:string" />
          </xsd:sequence>
        </xsd:complexType>
      </xsd:element>

      <xsd:element name="CreateSessionResponse">
        <xsd:complexType>
          <xsd:all>
            <xsd:element name="SessionStr" type="xsd:string" />
            <xsd:element name="OneTime" type="xsd:string" />
            <xsd:element name="Success" type="xsd:int" />
          </xsd:all>
        </xsd:complexType>
      </xsd:element>

    </xsd:schema>
  </types>
  <message name="CreateSessionSoapIn">
    <part name="parameters" element="s0:CreateSession" />
  </message>
  <message name="CreateSessionSoapOut">
    <part name="parameters" element="s0:CreateSessionResponse" />
  </message>
  <portType name="FastServicesSoap">
    <operation name="CreateSession">
      <input message="s0:CreateSessionSoapIn" />
      <output message="s0:CreateSessionSoapOut" />
    </operation>
  </portType>
  <binding name="FastServicesSoap" type="s0:FastServicesSoap">
    <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document" />
    <operation name="CreateSession">
      <soap:operation soapAction="http://www.fastmail.fm/SOAP/MessagingEngine/CreateSession" style="document" />
      <input>
        <soap:body use="literal" />
      </input>
      <output>
        <soap:body use="literal" />
      </output>
    </operation>
  </binding>
  <service name="FastServices">
    <port name="FastServicesSoap" binding="s0:FastServicesSoap">
      <soap:address location="http://www.fastmail.fm/SOAP/MessagingEngine" />
    </port>
  </service>
</definitions>

And the C# client code:
Code:
using System;
using System.Xml;
using System.Web.Services.Protocols;

namespace TestSoap
{
   class Class1
   {
      [STAThread]
      static void Main(string[] args)
      {
         TestSoap.FastServices.FastServices c=new TestSoap.FastServices.FastServices();
         bool bRetry=false;
         string SessionStr;
         string OneTime;
         int Success;
         try
         {
            SessionStr=c.CreateSession("johndoe",out OneTime,out Success);
         }
         catch(SoapException s)
         {
            c.Url=s.Actor+"MessagingEngine";
            bRetry=true;
         }
         if (bRetry)
         {
            SessionStr=c.CreateSession("johndoe",out OneTime,out Success);
            System.Console.Out.WriteLine(
               "Session: {0}\nOneTime: {1}\nSuccess: {2}",
               SessionStr,
               OneTime,
               Success);
         }
      }
   }
}


That's it!

I'm going to try to GetFolder call now...
Back to top
View user's profile Send private message Send e-mail Visit poster's website
eric_thiebaut
Site Admin


Joined: 07 Apr 2002
Posts: 1523
Location: Sydney, Australia

PostPosted: Fri Aug 29, 2003 10:43 am    Post subject: Reply with quote

Of course replace johndoe by your account name...

Very Happy Very Happy Very Happy Very Happy
Back to top
View user's profile Send private message Send e-mail Visit poster's website
rthomas



Joined: 25 Aug 2003
Posts: 11
Location: France, Lille

PostPosted: Fri Aug 29, 2003 10:50 am    Post subject: Reply with quote

It's working, great ! Smile
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Jeremy Howard
The "e" in e-mail


Joined: 09 Apr 2002
Posts: 325
Location: Melbourne

PostPosted: Fri Aug 29, 2003 12:17 pm    Post subject: Reply with quote

Well done gang! Smile

I'm thinking that for the hash/map problem, maybe we shouldn't use them in the API at all. Instead, anywhere we'd normally use a hash, instead return 2 arrays, one of the keys, one of the values. Slightly less convenient, but much more portable. What do you think?
Back to top
View user's profile Send private message Visit poster's website
Jeremy Howard
The "e" in e-mail


Joined: 09 Apr 2002
Posts: 325
Location: Melbourne

PostPosted: Fri Aug 29, 2003 12:18 pm    Post subject: Reply with quote

It's MD5, then Base64.

If you need more details, see the source of Digest::MD5 on CPAN.
Back to top
View user's profile Send private message Visit poster's website
eric_thiebaut
Site Admin


Joined: 07 Apr 2002
Posts: 1523
Location: Sydney, Australia

PostPosted: Fri Aug 29, 2003 12:44 pm    Post subject: Reply with quote

MD5 & Base64 sources are widely available in C, so this should be OK. (the current version of FastCheck already uses MD5 by the way). I reckon there must be a C# implementation somewhere too if needed.

I'll try to see about the hashes.

I'm of scuba diving this WE - preparing my instructor course Wink.
So I won't be able to work on it until Sunday night at best...
Back to top
View user's profile Send private message Send e-mail Visit poster's website
rthomas



Joined: 25 Aug 2003
Posts: 11
Location: France, Lille

PostPosted: Fri Aug 29, 2003 1:15 pm    Post subject: Reply with quote

Eric, this should work but I didn't test it "live".

Code:
static string GetOneTime(string oneTimeInit, string password)
      {
         System.Text.UTF8Encoding utf8 = new System.Text.UTF8Encoding();
         System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
         return Convert.ToBase64String(md5.ComputeHash(utf8.GetBytes(oneTimeInit+":"+password)));
      }


Jeremy for hash table the hash code you provide can be the hash key for us (the client side) and then can be easier for you.

Rémi
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Jeremy Howard
The "e" in e-mail


Joined: 09 Apr 2002
Posts: 325
Location: Melbourne

PostPosted: Fri Aug 29, 2003 4:23 pm    Post subject: Reply with quote

rthomas wrote:
Eric, this should work but I didn't test it "live".
We won't be hearing from Eric until next week I think... Let me know if you try this over the weekend.
Quote:
Jeremy for hash table the hash code you provide can be the hash key for us (the client side) and then can be easier for you.
Sorry, don't follow you. I'm talking up data structures that map from a key to a value, called 'dictionary', 'map', 'hashtable', etc in various languages. You know what I mean?
Back to top
View user's profile Send private message Visit poster's website
Jeremy Howard
The "e" in e-mail


Joined: 09 Apr 2002
Posts: 325
Location: Melbourne

PostPosted: Mon Sep 01, 2003 2:44 am    Post subject: Reply with quote

Eric, can you show me the complete code to build your example with the .Net SDK, not with VS.Net? I assume there's some other code to link the class to the WSDL file?
Back to top
View user's profile Send private message Visit poster's website
Jeremy Howard
The "e" in e-mail


Joined: 09 Apr 2002
Posts: 325
Location: Melbourne

PostPosted: Mon Sep 01, 2003 4:14 am    Post subject: Reply with quote

OK, I've got the .Net SDK version working. No additional code was required - I just had to create a proxy, following these instructions: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconbuildingaspnetwebserviceclients.asp

It's pretty cool that MS provides a free SDK now! Smile
Back to top
View user's profile Send private message Visit poster's website
robmueller



Joined: 01 Sep 2003
Posts: 1

PostPosted: Mon Sep 01, 2003 4:54 am    Post subject: GetFolderList... Reply with quote

Currently with the GetFolderList() call, it returns a bunch of folder info, including folder names something like this:

Code:

<Folder>
  <Name>inbox</Name>
  <Unread>10</Unread>
</Folder>
<Folder>
  <Name>inbox.blah</Name>
  <Unread>5</Unread>
</Folder>
<Folder>
  <Name>inbox.whatever</Name>
  <Unread>3</Unread>
</Folder>
<Folder>
  <Name>inbox.whatever.sub</Name>
  <Unread>1</Unread>
</Folder>


I'm not sure that making it a flat 'array' sort of thing, with the folder name showing the hierarchy nature is the best idea, namely because it assumes that '.' is the path separator, and why get a flat list for something that really is a hierarchy.

Would it be better to return something like:


Code:

<Folder>
  <Name>inbox</Name>
  <Unread>10</Unread>
  <SubFolders>
    <Folder>
      <Name>blah</Name>
      <Unread>5</Unread>
    </Folder>
    <Folder>
      <Name>whatever</Name>
      <Unread>3</Unread>
      <SubFolders>
        <Folder>
          <Name>sub</Name>
          <Unread>1</Unread>
        </Folder>
      </SubFolders>
    </Folder>
  </SubFolders
</Folder>


???

Rob
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    FastCheck Forum Index -> FastServices All times are GMT
Goto page 1, 2, 3, 4  Next
Page 1 of 4

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group