← Back to team overview

zorba-coders team mailing list archive

[Merge] lp:~zorba-coders/zorba/feature-setvar-typed--email into lp:zorba

 

Paul J. Lucas has proposed merging lp:~zorba-coders/zorba/feature-setvar-typed--email into lp:zorba.

Commit message:
Fixed #include.

Requested reviews:
  Paul J. Lucas (paul-lucas)

For more details, see:
https://code.launchpad.net/~zorba-coders/zorba/feature-setvar-typed--email/+merge/217844

Fixed #include.
-- 
https://code.launchpad.net/~zorba-coders/zorba/feature-setvar-typed--email/+merge/217844
Your team Zorba Coders is subscribed to branch lp:zorba.
=== added file 'CMakeLists.txt'
--- CMakeLists.txt	1970-01-01 00:00:00 +0000
+++ CMakeLists.txt	2014-04-30 23:07:12 +0000
@@ -0,0 +1,29 @@
+# Copyright 2006-2010 The FLWOR Foundation.
+# 
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+# 
+# http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+CMAKE_MINIMUM_REQUIRED (VERSION 2.6)
+
+PROJECT (zorba_email_module)
+ENABLE_TESTING ()
+INCLUDE (CTest)
+
+FIND_PACKAGE (Zorba REQUIRED HINTS "${ZORBA_BUILD_DIR}")
+INCLUDE ("${Zorba_USE_FILE}")
+
+SET_CMAKE_MODULE_PATH()
+
+ADD_TEST_DIRECTORY ("${PROJECT_SOURCE_DIR}/test")
+ADD_SUBDIRECTORY ("src")
+
+DONE_DECLARING_ZORBA_URIS ()

=== renamed file 'CMakeLists.txt' => 'CMakeLists.txt.moved'
=== added directory 'cmake_modules'
=== renamed directory 'cmake_modules' => 'cmake_modules.moved'
=== added file 'cmake_modules/FindCClient.cmake'
--- cmake_modules/FindCClient.cmake	1970-01-01 00:00:00 +0000
+++ cmake_modules/FindCClient.cmake	2014-04-30 23:07:12 +0000
@@ -0,0 +1,80 @@
+# Copyright 2006-2008 The FLWOR Foundation.
+# 
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+# 
+# http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# - Find the C-CLIENT library that is part of the UW IMAP toolkit
+#
+# Once done this will define
+#
+#  CCLIENT_FOUND        - True if C-CLIENT library found.
+#  CCLIENT_INCLUDE_DIRS - Directory to include to get C-CLIENT headers
+#  CCLIENT_LIBRARIES    - Libraries to link against for the C-CLIENT library
+#
+
+IF(CCLIENT_INCLUDE_DIRS AND CCLIENT_LIBRARIES)
+  # Already in cache, be silent
+  SET(CCLIENT_FIND_QUIETLY TRUE)
+ENDIF(CCLIENT_INCLUDE_DIRS AND CCLIENT_LIBRARIES)
+
+# Look for the headers.
+FIND_PATH(
+  CCLIENT_INCLUDE
+  NAMES c-client.h c-client/c-client.h
+  PATHS ${CCLIENT_INCLUDE_DIR} /usr/include/imap /usr/include/c-client /usr/local/include/c-client /opt/local/include/c-client
+  DOC "Include directory for the CCLient library headers (the path to 'c-client.h' file)")
+
+IF(CCLIENT_INCLUDE)
+  IF(WIN32)
+    IF(EXISTS "${CCLIENT_INCLUDE}/c-client/c-client.h")
+      SET(CCLIENT_INCLUDE "${CCLIENT_INCLUDE}/c-client" CACHE PATH "Path to a file." FORCE)
+    ENDIF(EXISTS "${CCLIENT_INCLUDE}/c-client/c-client.h")  
+  ENDIF(WIN32)
+  MESSAGE(STATUS "Found CCLIENT include directory -- " ${CCLIENT_INCLUDE})
+ELSE(CCLIENT_INCLUDE)
+  MESSAGE(STATUS "Could not find CCLIENT include directory")
+ENDIF(CCLIENT_INCLUDE)
+
+# only for GUI purposes
+MARK_AS_ADVANCED(CCLIENT_INCLUDE)
+
+# Look for the library.
+FIND_LIBRARY(
+  CCLIENT_LIBRARY
+  NAMES c-client.a libc-client.a c-client libc-client4.a c-client4 cclient.lib c-client/libc-client.a c-client/cclient.lib c-client/Release/cclient.lib
+  PATHS ${CCLIENT_LIBRARY_DIR} /usr/local/lib /opt/local/lib /usr/lib /usr/lib/c-client
+  DOC "Library to link against for the email support (c-client, libc-client or cclient.lib)")
+
+IF(CCLIENT_LIBRARY)
+  MESSAGE(STATUS "Found CCLIENT library -- " ${CCLIENT_LIBRARY})
+ELSE(CCLIENT_LIBRARY)
+  MESSAGE(STATUS "Could not find CCLIENT library")
+ENDIF(CCLIENT_LIBRARY)
+
+# Copy the results to the output variables.
+IF(CCLIENT_INCLUDE AND CCLIENT_LIBRARY)
+  SET(CCLIENT_FOUND 1)
+  SET(CCLIENT_LIBRARIES ${CCLIENT_LIBRARY})
+  SET(CCLIENT_INCLUDE_DIRS ${CCLIENT_INCLUDE})
+
+  # Do not treat the operator name keywords and, bitand, bitor, compl, not, or and xor
+  # as synonyms as keywords. Needed in order to include C-CLIENT library
+  IF(CMAKE_COMPILER_IS_GNUCXX)
+    IF(NOT CMAKE_CXX_FLAGS MATCHES "-fno-operator-names")
+      SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-operator-names")
+    ENDIF(NOT CMAKE_CXX_FLAGS MATCHES "-fno-operator-names")
+  ENDIF(CMAKE_COMPILER_IS_GNUCXX)
+ELSE(CCLIENT_INCLUDE AND CCLIENT_LIBRARY)
+  SET(CCLIENT_FOUND 0)
+  SET(CCLIENT_LIBRARIES)
+  SET(CCLIENT_INCLUDE_DIRS)
+ENDIF(CCLIENT_INCLUDE AND CCLIENT_LIBRARY)

=== added file 'cmake_modules/FindKerberos.cmake'
--- cmake_modules/FindKerberos.cmake	1970-01-01 00:00:00 +0000
+++ cmake_modules/FindKerberos.cmake	2014-04-30 23:07:12 +0000
@@ -0,0 +1,47 @@
+# Copyright 2006-2008 The FLWOR Foundation.
+# 
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+# 
+# http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Finds the KERBEROS library
+#
+#  KERBEROS_FOUND        - True if SASL library found.
+#  KERBEROS_LIBRARY      - Libraries to link against for the SASL library
+#
+
+if (KERBEROS_LIBRARIES)
+  # Already in cache, be silent
+ set(KERBEROS_FIND_QUIETLY TRUE)
+endif (KERBEROS_LIBRARIES)
+
+# Look for the library.
+find_library(
+  KERBEROS_LIBRARY
+  NAMES gssapi_krb5
+  PATHS ${KERBEROS_LIBRARY_DIRS} /opt/local/lib /usr/lib /usr/local/lib
+  DOC "Library to link against for kerberos support (gssapi_krb5)")
+mark_as_advanced(KERBEROS_LIBRARY)
+
+if (KERBEROS_LIBRARY)
+  MESSAGE(STATUS "Found Kerberos library -- " ${KERBEROS_LIBRARY})
+else (KERBEROS_LIBRARY)
+  MESSAGE(STATUS "Could not find Kerberos library")
+endif (KERBEROS_LIBRARY)
+
+# Copy the results to the output variables.
+if(KERBEROS_LIBRARY)
+  set(KERBEROS_FOUND 1)
+else(KERBEROS_LIBRARY)
+  set(KERBEROS_FOUND 0)
+  set(KERBEROS_LIBRARY)
+  set(KERBEROS_INCLUDE)
+endif(KERBEROS_LIBRARY)

=== added file 'cmake_modules/FindPAM.cmake'
--- cmake_modules/FindPAM.cmake	1970-01-01 00:00:00 +0000
+++ cmake_modules/FindPAM.cmake	2014-04-30 23:07:12 +0000
@@ -0,0 +1,37 @@
+# Copyright 2006-2008 The FLWOR Foundation.
+# 
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+# 
+# http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Try to find the PAM libraries
+#
+# PAM_FOUND       - True if PAM library found
+# PAM_INCLUDE_DIR - Directory to include to get PAM headers
+# PAM_LIBRARIES   - Libraries to link against for the PAM library
+
+if (PAM_INCLUDE_DIR AND PAM_LIBRARY)
+ # Already in cache, be silent
+ set(PAM_FIND_QUIETLY TRUE)
+endif (PAM_INCLUDE_DIR AND PAM_LIBRARY)
+
+find_path(PAM_INCLUDE_DIR NAMES security/pam_appl.h pam/pam_appl.h)
+find_library(PAM_LIBRARY pam)
+find_library(DL_LIBRARY dl)
+
+if (PAM_INCLUDE_DIR AND PAM_LIBRARY)
+ set(PAM_FOUND TRUE)
+  if (DL_LIBRARY)
+    set(PAM_LIBRARIES ${PAM_LIBRARY} ${DL_LIBRARY})
+  else (DL_LIBRARY)
+    set(PAM_LIBRARIES ${PAM_LIBRARY})
+  endif (DL_LIBRARY)
+endif (PAM_INCLUDE_DIR AND PAM_LIBRARY)

=== added directory 'cmake_modules/Windows'
=== added file 'cmake_modules/Windows/FindCClient.cmake'
--- cmake_modules/Windows/FindCClient.cmake	1970-01-01 00:00:00 +0000
+++ cmake_modules/Windows/FindCClient.cmake	2014-04-30 23:07:12 +0000
@@ -0,0 +1,34 @@
+# Copyright 2010 The FLWOR Foundation.
+# 
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+# 
+# http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# - Find the C-CLIENT library that is part of the UW IMAP toolkit on Windows
+#
+# This is a proxy module that calls the FindCClient.cmake module. Before
+# doing that, we try to guess where CClient might be on the user's machine.
+# The user should provide ZORBA_THIRD_PARTY_REQUIREMENTS which is a path where
+# the CClient directory can be found. The CClient directory must have "imap"
+# (case insensitive) in its name.
+#
+# This module helps the Windows user to avoid providing the following two
+# variables when building Zorba:
+# -D CCLIENT_INCLUDE="path_to_3rd_party_dir\*imap*\c-client"
+# -D CCLIENT_LIBRARY="path_to_3rd_party_dir\*imap*\c-client\Release\cclient.lib"
+#
+# See the FindCClient.cmake module shipped with Zorba for more information.
+
+FIND_PACKAGE_WIN32 (
+  NAME "CClient"
+  FOUND_VAR "CCLIENT_FOUND"
+  SEARCH_NAMES "imap;cclient;c-client"
+)

=== added directory 'examples'
=== added directory 'examples/Queries'
=== added directory 'examples/Queries/imap'
=== added file 'examples/Queries/imap/copy_example.xq'
--- examples/Queries/imap/copy_example.xq	1970-01-01 00:00:00 +0000
+++ examples/Queries/imap/copy_example.xq	2014-04-30 23:07:12 +0000
@@ -0,0 +1,23 @@
+(:
+ : This example shows how to use the copy function of the http://www.zorba-xquery.com/modules/email/imap module.
+ :
+ : First we search for a message with the word copy in the subject. When we have found this message, we
+ : use the copy function to copy it internally to the CopyFolder folder.
+ : This creates a new message in the copy folder with a own unique identifier and message sequence number.
+ :) 
+
+import module namespace imap = 'http://www.zorba-xquery.com/modules/email/imap';
+
+
+(: This variable contains the information of the account on the IMAP server. :) 
+let $hostInfo :=
+  <hostInfo xmlns="http://www.zorba-xquery.com/modules/email";>
+    <hostName>mail.28msec.com/novalidate-cert</hostName>
+    <userName>imaptest</userName>
+    <password>cclient</password>
+  </hostInfo>
+
+let $uids := imap:search($hostInfo, "INBOX", "SUBJECT copy2", true())
+
+return
+  imap:copy($hostInfo, "INBOX", "INBOX.CopyFolder", $uids, true())

=== added file 'examples/Queries/imap/create_rename_delete_example.xq'
--- examples/Queries/imap/create_rename_delete_example.xq	1970-01-01 00:00:00 +0000
+++ examples/Queries/imap/create_rename_delete_example.xq	2014-04-30 23:07:12 +0000
@@ -0,0 +1,36 @@
+(:
+ : This example shows how to use the create, delete  function of the
+ : http://www.zorba-xquery.com/modules/email/imap module.
+ :
+ : Using the host information stored in the variable $hostInfo a new mailbox
+ : is created on the mail.28msec.com server for this account.
+ :
+ : The mailbox name is partly random (to make sure that there is no other
+ : mailbox with that name). Then, we rename the mailbox to another random
+ : generated name. In the end the renamed mailbox is deleted to make sure that
+ : the account does not get swamped with useless mailboxes.
+ : 
+ : If no error is thrown, all operations were successful.
+ :) 
+
+import module namespace imap = 'http://www.zorba-xquery.com/modules/email/imap';
+import module namespace random = 'http://www.zorba-xquery.com/modules/random';
+
+
+(: This variable contains the information of the account on the IMAP server. :) 
+let $hostInfo :=
+  <hostInfo xmlns="http://www.zorba-xquery.com/modules/email";>
+    <hostName>mail.28msec.com/novalidate-cert</hostName>
+    <userName>imaptest</userName>
+    <password>cclient</password>
+  </hostInfo>
+
+let $mailboxName := fn:concat("INBOX.", fn:substring(random:uuid(), 0, 4))
+let $newMailboxName := fn:concat("INBOX.", fn:substring(random:uuid(), 0, 5))
+
+return
+  {
+    imap:create($hostInfo, $mailboxName);
+    imap:rename($hostInfo, $mailboxName, $newMailboxName);
+    imap:delete($hostInfo, $newMailboxName)
+  }

=== added file 'examples/Queries/imap/expunge_example.xq'
--- examples/Queries/imap/expunge_example.xq	1970-01-01 00:00:00 +0000
+++ examples/Queries/imap/expunge_example.xq	2014-04-30 23:07:12 +0000
@@ -0,0 +1,69 @@
+(:
+ : This example shows how to use the expunge function of the http://www.zorba-xquery.com/modules/email/imap module.
+ : Using the host information stored in the variable $hostInfo first the search function is used to get
+ : the unique id of the all messages with the word delete in its subject.
+ : Then the delete flag is set on these messages using the set-flags method of the imap-module.
+ : The call to expunge on the mailbox then deletes all messages that have the delete flag set.
+ : 
+ : This example is concluded by using the send function to send a new mail to the inbox to make sure that
+ : there will be a message to delete next time the example is used.
+ :) 
+
+import module namespace imap = 'http://www.zorba-xquery.com/modules/email/imap';
+import module namespace smtp = 'http://www.zorba-xquery.com/modules/email/smtp';
+
+
+(: This variable contains the information of the account on the IMAP server. :) 
+let $hostInfo :=
+  <hostInfo xmlns="http://www.zorba-xquery.com/modules/email";>
+    <hostName>mail.28msec.com/novalidate-cert</hostName>
+    <userName>imaptest</userName>
+    <password>cclient</password>
+  </hostInfo>
+
+(: This variable contains the information of the account from which the email should be sent. :) 
+let $senderHostInfo :=
+  <hostInfo xmlns="http://www.zorba-xquery.com/modules/email";>
+    <hostName>smtp.gmail.com:587/tls/novalidate-cert</hostName>
+    <userName>zorba.smtp.sender</userName>
+    <password>1openssl!</password>
+  </hostInfo>
+
+(: the XML representation of the email to be sent, as described by the XML schema
+   http://www.zorba-xquery.com/modules/email :)
+let $email := 
+  <message xmlns="http://www.zorba-xquery.com/modules/email";>
+    <envelope>
+      <date>2010-11-26T15:50:39-04:01</date>
+      <subject>delete</subject>
+      <recipient>
+        <to>
+          <name>Test Account</name>
+          <email>imaptest@xxxxxxxxxx</email>
+        </to>
+      </recipient>
+     </envelope>
+    <body>
+      <content contentType="text/plain" charset="UTF-8" contentTransferEncoding="ENC8BIT">
+        Oh yeah
+      </content>
+    </body>
+  </message>
+
+let $flags :=
+  <flags xmlns="http://www.zorba-xquery.com/modules/email";>
+    <deleted/>
+  </flags>
+
+let $ids := imap:search($hostInfo, "INBOX", "SUBJECT delete", true())
+return {
+  for $id in $ids
+  return
+    imap:set-flags($hostInfo, "INBOX", $id, $flags, true());
+
+  (: expunge from server :)
+  imap:expunge($hostInfo, "INBOX");
+
+  (: resend a "delete" message to have it next time when we execute this example :)
+  smtp:send($senderHostInfo, $email);
+}

=== added file 'examples/Queries/imap/fetch_envelope_example.xq'
--- examples/Queries/imap/fetch_envelope_example.xq	1970-01-01 00:00:00 +0000
+++ examples/Queries/imap/fetch_envelope_example.xq	2014-04-30 23:07:12 +0000
@@ -0,0 +1,51 @@
+(:
+ : This example shows how to use the fetch-envelope function of
+ : the http://www.zorba-xquery.com/modules/email/imap module.
+ :
+ : Using the host information stored in the variable $hostInfo, first a message
+ : containing the word "test" in the subject is searched for, using the search
+ : function. Then, the envelope of the first message found is fetched.
+ :
+ : The XML output of this script should look something like:
+ :
+ :  <envelope xmlns="http://www.zorba-xquery.com/modules/email";>
+ :    <date>2011-02-14T13:07:38</date>
+ :    <from>
+ :      <name>Daniel Thomas</name>
+ :      <email>thomas.daniel.james@xxxxxxxxx</email>
+ :    </from>
+ :    <sender>
+ :      <name>Daniel Thomas</name>
+ :      <email>thomas.daniel.james@xxxxxxxxx</email>
+ :    </sender>
+ :    <replyTo>
+ :      <name>Daniel Thomas</name>
+ :      <email>thomas.daniel.james@xxxxxxxxx</email>
+ :    </replyTo>
+ :    <subject>test</subject>
+ :    <recipient>
+ :      <to>
+ :        <email>imaptest@xxxxxxxxxx</email>
+ :      </to>
+ :    </recipient>
+ :    <messageId>&lt;AANLkTinSujfq9-UgGDvX+RcOrhvQf5JTnTdwSLNTiqZ5@xxxxxxxxxxxxxx&gt;</messageId>
+ :    <flags/>
+ :  </envelope>
+ :
+ : If no error is thrown, all operations were successful.
+ :) 
+
+import module namespace imap = 'http://www.zorba-xquery.com/modules/email/imap';
+
+
+(: This variable contains the information of the account on the IMAP server. :) 
+let $hostInfo :=
+  <hostInfo xmlns="http://www.zorba-xquery.com/modules/email";>
+    <hostName>mail.28msec.com/novalidate-cert</hostName>
+    <userName>imaptest</userName>
+    <password>cclient</password>
+  </hostInfo>
+
+let $uids := imap:search($hostInfo, "INBOX", "SUBJECT test", false())
+return
+  imap:fetch-envelope($hostInfo, "INBOX", $uids[1], false())

=== added file 'examples/Queries/imap/fetch_flags_example.xq'
--- examples/Queries/imap/fetch_flags_example.xq	1970-01-01 00:00:00 +0000
+++ examples/Queries/imap/fetch_flags_example.xq	2014-04-30 23:07:12 +0000
@@ -0,0 +1,33 @@
+(:
+ : This example shows how to use the fetch-flags function of the
+ : http://www.zorba-xquery.com/modules/email/imap module.
+ :
+ : First, the unique identifiers of all messages containing the word "flags" in
+ : the subject are retrieved. Then, the flags of the first message found is
+ : fetched.
+ : 
+ : The resulting XML should look something like this:
+ : 
+ :  <flags xmlns="http://www.zorba-xquery.com/modules/email";>
+ :    <seen/>
+ :    <answered/>
+ :  </flags>
+ :
+ : If no error is thrown, all operations were successful.
+ :) 
+
+import module namespace imap = 'http://www.zorba-xquery.com/modules/email/imap';
+
+
+(: This variable contains the information of the account on the IMAP server. :) 
+let $hostInfo :=
+  <hostInfo xmlns="http://www.zorba-xquery.com/modules/email";>
+    <hostName>mail.28msec.com/novalidate-cert</hostName>
+    <userName>imaptest</userName>
+    <password>cclient</password>
+  </hostInfo>
+
+let $uids := imap:search($hostInfo, "INBOX", "SUBJECT flags", true())
+
+return
+  imap:fetch-flags($hostInfo, "INBOX", $uids[1], true())

=== added file 'examples/Queries/imap/fetch_from_example.xq'
--- examples/Queries/imap/fetch_from_example.xq	1970-01-01 00:00:00 +0000
+++ examples/Queries/imap/fetch_from_example.xq	2014-04-30 23:07:12 +0000
@@ -0,0 +1,27 @@
+(:
+ : This example shows how to use the fetch-from function of the
+ : http://www.zorba-xquery.com/modules/email/imap module.
+ :
+ : First, the sequence numbers of all messages containing the word "flags" in
+ : the subject are retrieved. Then, the from field of the first message found
+ : is fetched. This contains the name and the email address of the sender.
+ :
+ : If no error is thrown, all operations were successful.
+ :) 
+
+import module namespace imap = 'http://www.zorba-xquery.com/modules/email/imap';
+
+
+(: This variable contains the information of the account on the IMAP server. :) 
+let $hostInfo :=
+  <hostInfo xmlns="http://www.zorba-xquery.com/modules/email";>
+    <hostName>mail.28msec.com/novalidate-cert</hostName>
+    <userName>imaptest</userName>
+    <password>cclient</password>
+  </hostInfo>
+
+
+let $uids := imap:search($hostInfo, "INBOX", "SUBJECT flags", false())
+
+return
+  imap:fetch-from($hostInfo, "INBOX", $uids[1])

=== added file 'examples/Queries/imap/fetch_message_example.xq'
--- examples/Queries/imap/fetch_message_example.xq	1970-01-01 00:00:00 +0000
+++ examples/Queries/imap/fetch_message_example.xq	2014-04-30 23:07:12 +0000
@@ -0,0 +1,46 @@
+(:
+ : This example shows how to use the fetch-message function of the
+ : http://www.zorba-xquery.com/modules/email/imap module.
+ :
+ : First, the sequence numbers of all messages containing the word "test" in
+ : the subject are retrieved. Then, the first message found is fetched.
+ :
+ : The resulting XML should look something like this:
+ :
+ :  <message xmlns="http://www.zorba-xquery.com/modules/email";>
+ :    <envelope>
+ :      <date>2011-02-14T13:07:38</date>
+ :      <from><name>Daniel Thomas</name><email>thomas.daniel.james@xxxxxxxxx</email></from>
+ :      <sender><name>Daniel Thomas</name><email>thomas.daniel.james@xxxxxxxxx</email></sender>
+ :      <replyTo><name>Daniel Thomas</name><email>thomas.daniel.james@xxxxxxxxx</email></replyTo>
+ :      <subject>test</subject><recipient><to><email>imaptest@xxxxxxxxxx</email></to></recipient>
+ :      <messageId>&lt;AANLkTinSujfq9-UgGDvX+RcOrhvQf5JTnTdwSLNTiqZ5@xxxxxxxxxxxxxx&gt;</messageId>
+ :      <flags/>
+ :    </envelope>
+ :    <mimeVersion>1.0</mimeVersion>
+ :    <body>
+ :      <multipart contentType="multipart/alternative" charset="us-ascii" contentTransferEncoding="ENC7BIT">
+ :        <content contentType="text/plain" charset="us-ascii" contentTransferEncoding="ENC8BIT">This is a test message&#xD;</content>
+ :        <content contentType="text/html" charset="us-ascii" contentTransferEncoding="ENC8BIT">This is a test message&#xD;</content>
+ :      </multipart>
+ :    </body>
+ :  </message>
+ :
+ : If no error is thrown, all operations were successful.
+ :) 
+
+import module namespace imap = 'http://www.zorba-xquery.com/modules/email/imap';
+
+
+(: This variable contains the information of the account on the IMAP server. :) 
+let $hostInfo :=
+  <hostInfo xmlns="http://www.zorba-xquery.com/modules/email";>
+    <hostName>mail.28msec.com/novalidate-cert</hostName>
+    <userName>imaptest</userName>
+    <password>cclient</password>
+  </hostInfo>
+
+let $uids := imap:search($hostInfo, "INBOX", "SUBJECT test", false())
+
+return
+  imap:fetch-message($hostInfo, "INBOX", $uids[1], false())  

=== added file 'examples/Queries/imap/fetch_message_sequence_number_example.xq'
--- examples/Queries/imap/fetch_message_sequence_number_example.xq	1970-01-01 00:00:00 +0000
+++ examples/Queries/imap/fetch_message_sequence_number_example.xq	2014-04-30 23:07:12 +0000
@@ -0,0 +1,26 @@
+(:
+ : This example shows how to use the fetch-message-sequence-number function of
+ : the http://www.zorba-xquery.com/modules/email/imap module.
+ :
+ : First, the unique identifiers of all messages containing the word "flags" in
+ : the subject are retrieved. Then, the message sequence number of the first
+ : message found is fetched.
+ :
+ : If no error is thrown, all operations were successful.
+ :) 
+
+import module namespace imap = 'http://www.zorba-xquery.com/modules/email/imap';
+
+
+(: This variable contains the information of the account on the IMAP server. :) 
+let $hostInfo :=
+  <hostInfo xmlns="http://www.zorba-xquery.com/modules/email";>
+    <hostName>mail.28msec.com/novalidate-cert</hostName>
+    <userName>imaptest</userName>
+    <password>cclient</password>
+  </hostInfo>
+
+let $sequenceNumbers := imap:search($hostInfo, "INBOX", "SUBJECT flags", true())
+
+return
+  imap:fetch-message-sequence-number($hostInfo, "INBOX", $sequenceNumbers[1])

=== added file 'examples/Queries/imap/fetch_subject_example.xq'
--- examples/Queries/imap/fetch_subject_example.xq	1970-01-01 00:00:00 +0000
+++ examples/Queries/imap/fetch_subject_example.xq	2014-04-30 23:07:12 +0000
@@ -0,0 +1,27 @@
+(:
+ : This example shows how to use the fetch-subject function of
+ : the http://www.zorba-xquery.com/modules/email/imap module.
+ :
+ : First, the message sequences number of all messages containing the word flags
+ : in the subject are retrieved. Then, the subject of the message found is
+ : fetched.
+ :
+ : If no error is thrown, all operations were successful.
+ :) 
+
+import module namespace imap = 'http://www.zorba-xquery.com/modules/email/imap';
+
+
+(: This variable contains the information of the account on the IMAP server. :) 
+let $hostInfo :=
+  <hostInfo xmlns="http://www.zorba-xquery.com/modules/email";>
+    <hostName>mail.28msec.com/novalidate-cert</hostName>
+    <userName>imaptest</userName>
+    <password>cclient</password>
+  </hostInfo>
+
+
+let $uids := imap:search($hostInfo, "INBOX", "SUBJECT flags", false())
+
+return
+  imap:fetch-subject($hostInfo, "INBOX", $uids[1])

=== added file 'examples/Queries/imap/fetch_uid_example.xq'
--- examples/Queries/imap/fetch_uid_example.xq	1970-01-01 00:00:00 +0000
+++ examples/Queries/imap/fetch_uid_example.xq	2014-04-30 23:07:12 +0000
@@ -0,0 +1,26 @@
+(:
+ : This example shows how to use the fetch-uid function of the
+ : http://www.zorba-xquery.com/modules/email/imap module.
+ :
+ : First, the message sequence numbers of all messages with the word "flags" in
+ : the subject are retrieved. Then, the unique identifier of the first message
+ : foundis fetched.
+ :
+ : If no error is thrown, all operations were successful.
+ :) 
+
+import module namespace imap = 'http://www.zorba-xquery.com/modules/email/imap';
+
+
+(: This variable contains the information of the account on the IMAP server. :) 
+let $hostInfo :=
+  <hostInfo xmlns="http://www.zorba-xquery.com/modules/email";>
+    <hostName>mail.28msec.com/novalidate-cert</hostName>
+    <userName>imaptest</userName>
+    <password>cclient</password>
+  </hostInfo>
+
+let $uids := imap:search($hostInfo, "INBOX", "SUBJECT flags", false())
+
+return
+  imap:fetch-uid($hostInfo, "INBOX", $uids[1])

=== added file 'examples/Queries/imap/list_example.xq'
--- examples/Queries/imap/list_example.xq	1970-01-01 00:00:00 +0000
+++ examples/Queries/imap/list_example.xq	2014-04-30 23:07:12 +0000
@@ -0,0 +1,38 @@
+(:
+ : This example shows how to use the list function of the
+ : http://www.zorba-xquery.com/modules/email/imap module.
+  :
+ : Using the host information stored in the variable $hostInfo, all folders on
+ : the given account that match the pattern "INBOX.Dr*" are listed.
+ :
+ : The resulting XML should look something like this:
+ : 
+ :  <mailbox xmlns="http://www.zorba-xquery.com/modules/email";>
+ :    <hostName/>
+ :    <mailboxName>INBOX.Drafts</mailboxName>
+ :  </mailbox> 
+ : 
+ : The parameters for the list function are interesting. The second parameter
+ : is applied to the pattern in an implementation dependent fashion to search
+ : for matching mailbox names. At this point we haven't found an example where
+ : this could be useful or even usable, so you could pass the empty string.
+ :
+ : The fourth and last parameter lets you choose if only subscribed mailboxes
+ : should be considered for the search.
+ :
+ : If no error is thrown, all operations were successful.
+ :) 
+
+import module namespace imap = 'http://www.zorba-xquery.com/modules/email/imap';
+
+
+(: This variable contains the information of the account on the IMAP server. :) 
+let $hostInfo :=
+  <hostInfo xmlns="http://www.zorba-xquery.com/modules/email";>
+    <hostName>mail.28msec.com/novalidate-cert</hostName>
+    <userName>imaptest</userName>
+    <password>cclient</password>
+  </hostInfo>
+
+return
+  imap:list($hostInfo, "", "INBOX.Dra*", false())

=== added file 'examples/Queries/imap/mimetypes_example.xq'
--- examples/Queries/imap/mimetypes_example.xq	1970-01-01 00:00:00 +0000
+++ examples/Queries/imap/mimetypes_example.xq	2014-04-30 23:07:12 +0000
@@ -0,0 +1,44 @@
+(:
+ : This should issue 4
+ :) 
+
+import schema namespace email = 'http://www.zorba-xquery.com/modules/email';
+
+let $messages := 
+  for $type in ("application/3gpp-ims+xml","application/cals-1840","application/pkcs7-signature","application/vnd.openxmlformats-officedocument.presentationml.comments+xml")
+  return
+    fn:validate {
+      <email:message xmlns:email="http://www.zorba-xquery.com/modules/email/email";>
+        <envelope>
+          <date>2010-11-26T15:50:39</date>
+          <from>
+            <email>zorba.smtp.sender@xxxxxxxxx</email>
+          </from>
+          <sender>
+            <email>zorba.smtp.sender@xxxxxxxxx</email>
+          </sender>
+          <replyTo>
+            <email>zorba.smtp.sender@xxxxxxxxx</email>
+          </replyTo>
+          <subject>RegexTest</subject>
+          <recipient>
+            <to>
+              <email>imaptest@xxxxxxxxxx</email>
+            </to>
+          </recipient>
+          <messageId>&lt;4ea85e91.679e440a.0f97.241e@xxxxxxxxxxxxx&gt;</messageId>
+          <flags>
+            <seen/>
+          </flags>
+        </envelope>
+        <mimeVersion>1.0</mimeVersion>
+        <body>
+          <multipart contentType="multipart/mixed" charset="us-ascii" contentTransferEncoding="ENC7BIT">
+            <content contentType="text/plain" charset="us-ascii" contentTransferEncoding="ENCQUOTEDPRINTABLE">=0A          Zorba really rocks. =0A        </content>
+            <content contentType="{$type}" charset="us-ascii" contentTransferEncoding="ENCBASE64" contentDisposition="the-truth.gif">some content</content>
+          </multipart>
+        </body>
+      </email:message>
+    }
+return
+  fn:count($messages)

=== added file 'examples/Queries/imap/move_example.xq'
--- examples/Queries/imap/move_example.xq	1970-01-01 00:00:00 +0000
+++ examples/Queries/imap/move_example.xq	2014-04-30 23:07:12 +0000
@@ -0,0 +1,30 @@
+(:
+ : This example shows how to use the move function of the
+ : http://www.zorba-xquery.com/modules/email/imap module.
+ :
+ : First, we search in the "INBOX.MoveFolder" mailbox for messages containing
+ : the word "move" in the subject. If such messages are found, they are moved
+ : to the INBOX. If not messages were found in the "INBOX.MoveFolder" mailbox,
+ : the move is performed inthe other direction.
+ :) 
+
+import module namespace imap = 'http://www.zorba-xquery.com/modules/email/imap';
+
+
+(: This variable contains the information of the account on the IMAP server. :) 
+let $hostInfo :=
+  <hostInfo xmlns="http://www.zorba-xquery.com/modules/email";>
+    <hostName>mail.28msec.com/novalidate-cert</hostName>
+    <userName>imaptest</userName>
+    <password>cclient</password>
+  </hostInfo>
+
+let $uids := imap:search($hostInfo, "INBOX.MoveFolder", "SUBJECT move", true())
+
+return
+  if ($uids) then
+    imap:move($hostInfo, "INBOX.MoveFolder", "INBOX", $uids, true());
+  else
+    let $uids := imap:search($hostInfo, "INBOX", "SUBJECT move", true())
+    return
+      imap:move($hostInfo, "INBOX", "INBOX.MoveFolder", $uids, true())

=== added file 'examples/Queries/imap/search_example.xq'
--- examples/Queries/imap/search_example.xq	1970-01-01 00:00:00 +0000
+++ examples/Queries/imap/search_example.xq	2014-04-30 23:07:12 +0000
@@ -0,0 +1,27 @@
+(:
+ : This example shows how to use the search function of the
+ : http://www.zorba-xquery.com/modules/email/imap module.
+ :
+ : The mailbox INBOX of the user described by the $hostInfo variable is
+ : searched for messages containing the word "test" in their subject.
+ :
+ : The search function returns the sequence of unique identifiers of mesages
+ : that comply with the search criteria. By setting the last argument to
+ : fn:false(), the message sequence numbers are returned instead.
+ :
+ : If no error is thrown, all operations were successful.
+ :) 
+
+import module namespace imap = 'http://www.zorba-xquery.com/modules/email/imap';
+
+
+(: This variable contains the information of the account on the IMAP server. :) 
+let $hostInfo :=
+  <hostInfo xmlns="http://www.zorba-xquery.com/modules/email";>
+    <hostName>mail.28msec.com/novalidate-cert</hostName>
+    <userName>imaptest</userName>
+    <password>cclient</password>
+  </hostInfo>
+
+return
+  imap:search($hostInfo, "INBOX", "SUBJECT test", true())

=== added file 'examples/Queries/imap/set_flags_example.xq'
--- examples/Queries/imap/set_flags_example.xq	1970-01-01 00:00:00 +0000
+++ examples/Queries/imap/set_flags_example.xq	2014-04-30 23:07:12 +0000
@@ -0,0 +1,35 @@
+(:
+ : This example shows how to use the set-flags function of the
+ : http://www.zorba-xquery.com/modules/email/imap module.
+ :
+ : First, the unique identifiers of all messages containing the word "flags" in
+ : the subject are retrieved. Then, the flags of the first of the message found
+ : are set to "seen" and "answered".
+ :
+ : The message will henceforth have exactly the flags that were set using the
+ : XML structure, so all the existing flag before this call are lost.
+ : 
+ : If no error is thrown, all operations were successful.
+ :) 
+
+import module namespace imap = 'http://www.zorba-xquery.com/modules/email/imap';
+
+
+(: This variable contains the information of the account on the IMAP server. :) 
+let $hostInfo :=
+  <hostInfo xmlns="http://www.zorba-xquery.com/modules/email";>
+    <hostName>mail.28msec.com/novalidate-cert</hostName>
+    <userName>imaptest</userName>
+    <password>cclient</password>
+  </hostInfo>
+
+let $uids := imap:search($hostInfo, "INBOX", "SUBJECT flags", true())
+
+let $flags :=
+  <flags xmlns="http://www.zorba-xquery.com/modules/email";>
+    <seen/>
+    <answered/>
+  </flags>
+
+return
+  imap:set-flags($hostInfo, "INBOX", $uids[1], $flags, true())
\ No newline at end of file

=== added file 'examples/Queries/imap/status_example.xq'
--- examples/Queries/imap/status_example.xq	1970-01-01 00:00:00 +0000
+++ examples/Queries/imap/status_example.xq	2014-04-30 23:07:12 +0000
@@ -0,0 +1,33 @@
+(:
+ : This example shows how to use the status function of the
+ : http://www.zorba-xquery.com/modules/email/imap module.
+ :
+ : Using the host information stored in the variable $hostInfo, the account
+ : status of the user imaptest on the mail.28msec.com server is retrieved.
+ :
+ : The XML output of this script should look something like:
+ :
+ :  <status xmlns:imaps="http://www.zorba-xquery.com/modules/email";>
+ :    <messages>27</messages>
+ :    <recent>0</recent>
+ :    <unseen>5</unseen>
+ :    <uidnext>77</uidnext>
+ :    <uidvalidity>1285079359</uidvalidity>
+ :  </status>
+ :
+ : If no error is thrown, all operations were successful.
+ :) 
+
+import module namespace imap = 'http://www.zorba-xquery.com/modules/email/imap';
+
+
+(: This variable contains the information of the account on the IMAP server. :) 
+let $hostInfo :=
+  <hostInfo xmlns="http://www.zorba-xquery.com/modules/email";>
+    <hostName>mail.28msec.com/novalidate-cert</hostName>
+    <userName>imaptest</userName>
+    <password>cclient</password>
+  </hostInfo>
+
+return
+  imap:status($hostInfo, "INBOX")

=== added file 'examples/Queries/imap/subscribe_unsubscribe_example.xq'
--- examples/Queries/imap/subscribe_unsubscribe_example.xq	1970-01-01 00:00:00 +0000
+++ examples/Queries/imap/subscribe_unsubscribe_example.xq	2014-04-30 23:07:12 +0000
@@ -0,0 +1,29 @@
+(:
+ : This example shows how to use the subscribe and unsubscribe functions of the
+ : http://www.zorba-xquery.com/modules/email/imap module.
+ :
+ : Using the host information stored in the variable $hostInfo the user
+ : imaptest is subscribed to the folder INBOX.Test on the account. After this,
+ : the user is unsubscribed from this folder using the unsubscribe function.
+ :
+ : Subscribing to a folder will make the folder visible for email clients that
+ : by default only list the subscribed folders.
+ :
+ : If no error is thrown, all operations were successful.
+ :) 
+
+import module namespace imap = 'http://www.zorba-xquery.com/modules/email/imap';
+
+(: This variable contains the information of the account on the IMAP server. :) 
+let $hostInfo :=
+  <hostInfo xmlns="http://www.zorba-xquery.com/modules/email";>
+    <hostName>mail.28msec.com/novalidate-cert</hostName>
+    <userName>imaptest</userName>
+    <password>cclient</password>
+  </hostInfo>
+
+return
+  {
+    imap:subscribe($hostInfo, "INBOX.Test");
+    imap:unsubscribe($hostInfo, "INBOX.Test")
+  }

=== added directory 'examples/Queries/smtp'
=== added file 'examples/Queries/smtp/html.xq'
--- examples/Queries/smtp/html.xq	1970-01-01 00:00:00 +0000
+++ examples/Queries/smtp/html.xq	2014-04-30 23:07:12 +0000
@@ -0,0 +1,57 @@
+(:
+ : This example uses the send function of the SMTP module to send an email
+ : containing an HTML message from a GMail account.
+ : This message is also sent to the sender itself in CC.
+ :)
+
+import module namespace smtp = 'http://www.zorba-xquery.com/modules/email/smtp'; 
+
+
+(: Note the use of the serialize function to create a string from the HTML content. :)
+let $htmlContent := fn:serialize(
+    <html>
+      <head></head>
+      <body>
+        <h1>Zorba really rocks.</h1>
+        <p>XQuery brought to a new level</p>
+      </body>
+    </html>
+  )
+
+(: This variable contains the information of the account from which the email should be sent. :) 
+let $hostInfo :=
+  <hostInfo xmlns="http://www.zorba-xquery.com/modules/email";>
+    <hostName>smtp.gmail.com:587/tls/novalidate-cert</hostName>
+    <userName>zorba.smtp.sender</userName>
+    <password>1openssl!!</password>
+  </hostInfo>
+
+(: the XML representation of the email to be sent, as described by the XML schema
+   http://www.zorba-xquery.com/modules/email :)
+let $email := 
+  <message xmlns="http://www.zorba-xquery.com/modules/email";>
+    <envelope>
+      <date>2010-11-26T15:50:39-04:01</date>
+      <subject>An important HTML message</subject>
+      <recipient>
+        <to>
+          <name>Test Account</name>
+          <email>imaptest@xxxxxxxxxx</email>
+        </to>
+      </recipient>
+      <recipient>
+        <cc>
+          <name>Myself</name>
+          <email>zorba.smtp.sender@xxxxxxxxx</email>
+        </cc>
+      </recipient>
+    </envelope>
+    <body>
+      <content contentType="text/html" charset="UTF-8" contentTransferEncoding="ENC8BIT">{ 
+        $htmlContent
+      }</content>
+    </body>
+  </message>
+
+return
+  smtp:send($hostInfo, $email)

=== added file 'examples/Queries/smtp/html_text_alternative.xq'
--- examples/Queries/smtp/html_text_alternative.xq	1970-01-01 00:00:00 +0000
+++ examples/Queries/smtp/html_text_alternative.xq	2014-04-30 23:07:12 +0000
@@ -0,0 +1,68 @@
+(:
+ : This example uses the send function of the SMTP module to send an email
+ : containing an HTML and text message from a GMail account. The order of the
+ : alternative contents might be relevant for some email clients. There is
+ : though a rule of thumb saying that the alternatives must be ordered in from
+ : the least to the most faithful representation. That is in our case, HTML
+ : version comes after the text version. This way email clients can stop at the
+ : email version they can still process. This message is also sent to the sender
+ : itself in CC.
+ :)
+
+import module namespace smtp = 'http://www.zorba-xquery.com/modules/email/smtp'; 
+
+
+(: Note the use of the serialize function to create a string from the HTML content. :)
+let $htmlContent := fn:serialize(
+    <html>
+      <head></head>
+      <body>
+        <h1>Zorba really rocks.</h1>
+        <p>XQuery brought to a new level</p>
+      </body>
+    </html>
+  )
+let $textContent := "Simple text version ... get yourself a nice and fancy email client."
+
+(: This variable contains the information of the account from which the email should be sent. :) 
+let $hostInfo :=
+  <hostInfo xmlns="http://www.zorba-xquery.com/modules/email";>
+    <hostName>smtp.gmail.com:587/tls/novalidate-cert</hostName>
+    <userName>zorba.smtp.sender</userName>
+    <password>1openssl!!</password>
+  </hostInfo>
+
+(: the XML representation of the email to be sent, as described by the XML schema
+   http://www.zorba-xquery.com/modules/email :)
+let $email := 
+  <message xmlns="http://www.zorba-xquery.com/modules/email";>
+    <envelope>
+      <date>2010-11-26T15:50:39-04:01</date>
+      <subject>An important HTML or Text message</subject>
+      <recipient>
+        <to>
+          <name>Test Account</name>
+          <email>imaptest@xxxxxxxxxx</email>
+        </to>
+      </recipient>
+      <recipient>
+        <cc>
+          <name>Myself</name>
+          <email>zorba.smtp.sender@xxxxxxxxx</email>
+        </cc>
+      </recipient>
+    </envelope>
+    <body>
+      <multipart contentType="multipart/alternative" charset="UTF-8" contentTransferEncoding="ENC8BIT">
+        <content contentType="text/html" charset="UTF-8" contentTransferEncoding="ENC8BIT">{  
+          $htmlContent
+        }</content>
+        <content contentType="text/plain" charset="UTF-8" contentTransferEncoding="ENC8BIT">{
+          $textContent
+        }</content>
+      </multipart>  
+    </body>
+  </message>
+
+return
+  smtp:send($hostInfo, $email)

=== added file 'examples/Queries/smtp/simple_text.xq'
--- examples/Queries/smtp/simple_text.xq	1970-01-01 00:00:00 +0000
+++ examples/Queries/smtp/simple_text.xq	2014-04-30 23:07:12 +0000
@@ -0,0 +1,39 @@
+(:
+ : This example uses the send function of the SMTP module to send an email
+ : containing a simple text message from a GMail account.
+ :)
+
+import module namespace smtp = 'http://www.zorba-xquery.com/modules/email/smtp'; 
+
+
+(: This variable contains the information of the account from which the email should be sent. :) 
+let $hostInfo :=
+  <hostInfo xmlns="http://www.zorba-xquery.com/modules/email";>
+    <hostName>smtp.gmail.com:587/tls/novalidate-cert</hostName>
+    <userName>zorba.smtp.sender</userName>
+    <password>1openssl!!</password>
+  </hostInfo>
+
+(: the XML representation of the email to be sent, as described by the XML schema
+   http://www.zorba-xquery.com/modules/email :)
+let $email := 
+  <message xmlns="http://www.zorba-xquery.com/modules/email";>
+    <envelope>
+      <date>2010-11-26T15:50:39-04:01</date>
+      <subject>An important message</subject>
+      <recipient>
+        <to>
+          <name>Test Account</name>
+          <email>imaptest@xxxxxxxxxx</email>
+        </to>
+      </recipient>
+    </envelope>
+    <body>
+      <content contentType="text/plain" charset="UTF-8" contentTransferEncoding="ENC8BIT">
+        Zorba really rocks. 
+      </content>
+    </body>
+  </message>
+
+return
+  smtp:send($hostInfo, $email)

=== added file 'examples/Queries/smtp/text_with_image.xq'
--- examples/Queries/smtp/text_with_image.xq	1970-01-01 00:00:00 +0000
+++ examples/Queries/smtp/text_with_image.xq	2014-04-30 23:07:12 +0000
@@ -0,0 +1,62 @@
+(:
+ : This example uses the send function of the SMTP module to send an email
+ : containing a simple text message with an image as attachement from a GMail
+ : account.
+ : To make things really interesting, the image is made on the spot with the
+ : help o the image modules available in Zorba.
+ :)
+
+import module namespace smtp = 'http://www.zorba-xquery.com/modules/email/smtp'; 
+import module namespace basic = 'http://www.zorba-xquery.com/modules/image/basic';
+import module namespace paint = 'http://www.zorba-xquery.com/modules/image/paint';
+
+
+(: This variable contains the information of the account from which the email should be sent. :) 
+let $hostInfo :=
+  <hostInfo xmlns="http://www.zorba-xquery.com/modules/email";>
+    <hostName>smtp.gmail.com:587/tls/novalidate-cert</hostName>
+    <userName>zorba.smtp.sender</userName>
+    <password>1openssl!!</password>
+  </hostInfo>
+
+(: The base64 representation of the image to be sent. :) 
+let $image := paint:paint(
+  basic:create(xs:unsignedInt(200), xs:unsignedInt(200), "GIF"),
+  <text xmlns="http://www.zorba-xquery.com/modules/image/image";>
+    <origin><x>20</x><y>50</y></origin>
+    <text>Zorba really rocks.</text>
+    <font>Arial</font>
+    <font-size>14</font-size>
+  </text>)
+
+(: the XML representation of the email to be sent, as described by the XML schema
+   http://www.zorba-xquery.com/modules/email :)
+let $email := 
+  <message xmlns="http://www.zorba-xquery.com/modules/email";>
+    <envelope>
+      <date>2010-11-26T15:50:39-04:01</date>
+      <subject>An important Image message</subject>
+      <recipient>
+        <to>
+          <name>Test Account</name>
+          <email>imaptest@xxxxxxxxxx</email>
+        </to>
+      </recipient>
+    </envelope>
+    <body>
+      <multipart contentType="multipart/mixed" charset="UTF-8" contentTransferEncoding="ENC8BIT">
+        <content contentType="text/plain" charset="UTF-8" contentTransferEncoding="ENC8BIT">
+          Zorba really rocks. 
+        </content>
+        <content contentType="image/gif" charset="UTF-8" contentTransferEncoding="ENCBASE64"
+          contentDisposition="attachement" contentDisposition-filename="the-truth.gif">{
+
+          $image
+
+        }</content>
+      </multipart>  
+    </body>
+  </message>
+
+return
+  smtp:send($hostInfo, $email)

=== added directory 'src'
=== renamed directory 'src' => 'src.moved'
=== added file 'src/CMakeLists.txt'
--- src/CMakeLists.txt	1970-01-01 00:00:00 +0000
+++ src/CMakeLists.txt	2014-04-30 23:07:12 +0000
@@ -0,0 +1,20 @@
+# Copyright 2006-2008 The FLWOR Foundation.
+# 
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+# 
+# http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# all external module libraries are generated in the directory
+# of the corresponding .xq file
+MESSAGE(STATUS "Add com")
+ADD_SUBDIRECTORY(com)
+
+MESSAGE(STATUS "End modules")

=== added directory 'src/com'
=== added file 'src/com/CMakeLists.txt'
--- src/com/CMakeLists.txt	1970-01-01 00:00:00 +0000
+++ src/com/CMakeLists.txt	2014-04-30 23:07:12 +0000
@@ -0,0 +1,14 @@
+# Copyright 2006-2008 The FLWOR Foundation.
+# 
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+# 
+# http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+ADD_SUBDIRECTORY(zorba-xquery)

=== added directory 'src/com/zorba-xquery'
=== added file 'src/com/zorba-xquery/CMakeLists.txt'
--- src/com/zorba-xquery/CMakeLists.txt	1970-01-01 00:00:00 +0000
+++ src/com/zorba-xquery/CMakeLists.txt	2014-04-30 23:07:12 +0000
@@ -0,0 +1,14 @@
+# Copyright 2006-2008 The FLWOR Foundation.
+# 
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+# 
+# http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+ADD_SUBDIRECTORY(www)

=== added directory 'src/com/zorba-xquery/www'
=== added file 'src/com/zorba-xquery/www/CMakeLists.txt'
--- src/com/zorba-xquery/www/CMakeLists.txt	1970-01-01 00:00:00 +0000
+++ src/com/zorba-xquery/www/CMakeLists.txt	2014-04-30 23:07:12 +0000
@@ -0,0 +1,14 @@
+# Copyright 2006-2008 The FLWOR Foundation.
+# 
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+# 
+# http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+ADD_SUBDIRECTORY(modules)

=== added directory 'src/com/zorba-xquery/www/modules'
=== added file 'src/com/zorba-xquery/www/modules/CMakeLists.txt'
--- src/com/zorba-xquery/www/modules/CMakeLists.txt	1970-01-01 00:00:00 +0000
+++ src/com/zorba-xquery/www/modules/CMakeLists.txt	2014-04-30 23:07:12 +0000
@@ -0,0 +1,14 @@
+# Copyright 2006-2008 The FLWOR Foundation.
+# 
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+# 
+# http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+ADD_SUBDIRECTORY(email)

=== added directory 'src/com/zorba-xquery/www/modules/email'
=== added file 'src/com/zorba-xquery/www/modules/email/CMakeLists.txt'
--- src/com/zorba-xquery/www/modules/email/CMakeLists.txt	1970-01-01 00:00:00 +0000
+++ src/com/zorba-xquery/www/modules/email/CMakeLists.txt	2014-04-30 23:07:12 +0000
@@ -0,0 +1,87 @@
+# Copyright 2006-2008 The FLWOR Foundation.
+# 
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+# 
+# http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# CClient library part of the UW IMAP toolkit required by the email
+# functionality
+IF (ZORBA_SUPPRESS_CCLIENT)
+  MESSAGE(STATUS "ZORBA_SUPPRESS_CCLIENT is true - not searching for C-Client")
+ELSE(ZORBA_SUPPRESS_CCLIENT)
+  MESSAGE (STATUS "Looking for CClient")
+  FIND_PACKAGE (CClient)
+
+  IF (NOT WIN32 AND NOT CYGWIN)
+    FIND_PACKAGE(OpenSSL)
+    FIND_PACKAGE(PAM)
+    FIND_PACKAGE(Kerberos)
+  ENDIF (NOT WIN32 AND NOT CYGWIN)
+
+  IF(CCLIENT_FOUND)
+    SET(SMTP_LINK_LIBRARIES ${CCLIENT_LIBRARIES})
+  
+    IF (OPENSSL_FOUND)
+      LIST(APPEND SMTP_LINK_LIBRARIES ${OPENSSL_LIBRARIES})
+      LIST(APPEND SMTP_LINK_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
+    ELSE (OPENSSL_FOUND)
+      MESSAGE(STATUS "CClient library found but OpenSSL not found. This may cause runtime problems on certain platforms where CClient is linked against OpenSSL by default, including MacOS X and Ubuntu Linux (and probably others). See this module's README.txt for more information.")
+    ENDIF (OPENSSL_FOUND)
+  
+    # Mac Ports and Ubuntu compiles CCLient with kerberos support by default.
+    IF(KERBEROS_FOUND)
+      LIST(APPEND SMTP_LINK_LIBRARIES ${KERBEROS_LIBRARY})
+    ELSE (KERBEROS_FOUND)
+      MESSAGE(STATUS "CClient library found but Kerberos not found. This may cause runtime problems on certain platforms where CClient is linked against Kerberos by default, including MacOS X and Ubuntu Linux (and probably others). See this module's README.txt for more information.")
+    ENDIF (KERBEROS_FOUND)
+    
+    INCLUDE_DIRECTORIES(${CCLIENT_INCLUDE_DIRS})
+    IF (NOT WIN32 AND NOT CYGWIN)
+      LIST(APPEND SMTP_LINK_LIBRARIES ${PAM_LIBRARIES})
+    ELSE (NOT WIN32 AND NOT CYGWIN)
+      LIST(APPEND SMTP_LINK_LIBRARIES secur32.lib crypt32.lib winmm.lib ws2_32.lib)
+    ENDIF (NOT WIN32 AND NOT CYGWIN)
+   
+    # including shared c-client library
+    ADD_LIBRARY (imap_commons STATIC
+      cclient/imap_client.cpp
+      cclient/email_exception.cpp
+    )
+    SET_TARGET_PROPERTIES (imap_commons PROPERTIES
+      FOLDER "Modules"
+    )
+
+    IF(UNIX AND NOT WIN32)
+      ADD_DEFINITIONS(-fPIC)
+
+      # option needed to make c-client compilable with clang
+      IF (CLANG)
+        SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fms-compatibility")
+      ENDIF()
+
+    ENDIF(UNIX AND NOT WIN32)
+
+    TARGET_LINK_LIBRARIES(imap_commons ${SMTP_LINK_LIBRARIES})
+    INCLUDE_DIRECTORIES("cclient")
+  
+  
+    DECLARE_ZORBA_SCHEMA (FILE email.xsd
+      URI "http://www.zorba-xquery.com/modules/email";)
+    DECLARE_ZORBA_MODULE (URI "http://www.zorba-xquery.com/modules/email/smtp"; VERSION 1.0 FILE "smtp.xq" LINK_LIBRARIES "imap_commons;${SMTP_LINK_LIBRARIES}")
+    DECLARE_ZORBA_MODULE (URI "http://www.zorba-xquery.com/modules/email/imap"; VERSION 1.0 FILE "imap.xq" LINK_LIBRARIES "imap_commons;${SMTP_LINK_LIBRARIES}")
+  
+  ELSE(CCLIENT_FOUND)
+  
+    MESSAGE(STATUS "CClient library not found -- if you want to use Email functionality please set CCLIENT_INCLUDE_DIRS and CCLIENT_LIBRARIES parameters.")
+  
+  ENDIF(CCLIENT_FOUND)
+ENDIF(ZORBA_SUPPRESS_CCLIENT)
+MESSAGE(STATUS "")

=== added file 'src/com/zorba-xquery/www/modules/email/README.txt'
--- src/com/zorba-xquery/www/modules/email/README.txt	1970-01-01 00:00:00 +0000
+++ src/com/zorba-xquery/www/modules/email/README.txt	2014-04-30 23:07:12 +0000
@@ -0,0 +1,50 @@
+These library modules need the c-client library installed to work properly.
+Here are a few notes that should help in doing this.
+
+Building IMAP CClient
+
+Zorba provides email (smtp and imap) support using the CClient library part of thei UW IMAP toolkit found at http://www.washington.edu/imap/.
+
+Unix/Linux/Mac OS
+Notes:
+  - There are some known issues with the CClient packages that come with diffrent Linux distributions.
+  - On x32 bit OpenSuse and also on x64 bit Ubuntu we noticed that the CClient shared library is broken (undefined symbol: mm_dlog).
+  - Due to that fact that Mark Crispin (the creator of CClient library) does not support CClient as a shared library but only as a static library (see FAQs shared library at http://www.washington.edu/imap/IMAP-FAQs/index.html#6.3), we strongly suggest you want to get the UW IMAP toolkit</a> and compile it yourself.
+- On Linux 64-bit, you might discover a problem with the optional package cclient. E.g. on Ubuntu 64-bit, you might discover the following:
+
+Linking CXX shared library libsmtp.so
+/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/4.4.3/../../../../lib/libc-client.a(osdep.o): relocation R_X86_64_32 against
+  `server_input_wait' can not be used when making a shared object; recompile with -fPIC
+/usr/lib/gcc/x86_64-linux-gnu/4.4.3/../../../../lib/libc-client.a: could not read symbols: Bad value
+e
+  To fix this, you need to compile CClient yourself. The commands to compile CClient correctly are:
+ 
+cd <some_directory>
+wget ftp://ftp.cac.washington.edu/imap/imap-2007e.tar.gz
+tar -xf imap-2007e.tar.gz
+cd imap-2007e
+make slx EXTRACFLAGS="-I/usr/include/openssl -fPIC"
+  
+
+  - Also please keep in mind that if SSL/TLS authentication is required by the SMTP server, then you first need to install OpenSSL found at http://www.openssl.org/ and configure CClient to use it.
+  - Make sure the name of the library is prefixed by 'lib' and suffixed with '.a' (for example libc-client.a on Linux/Unix or libc-client4.a on Mac OS).
+
+Use the following extra CMake arguments when building Zorba:
+
+-D CCLIENT_INCLUDE="path_to_imap-2007e\c-client"
+-D CCLIENT_LIBRARY="path_to_imap-2007e\c-client\libc-client.a"
+
+Here are some quick suggestions to build CClient on Linux:
+- x32-bit Linux: make lnp
+- x64-bit Linux: make lnp  EXTRACFLAGS="-I/usr/include/openssl -fPIC" EXTRAAUTHENTICATORS=gss in order to build with SSL and Kerberos support.
+
+For more detailed build instructions please check out the Server Documentation at http://www.washington.edu/imap/documentation and the UW IMAP FAQs at http://www.washington.edu/imap/IMAP-FAQs/index.html
+
+Windows
+You must build the UW IMAP toolkit yourself.
+
+Use the following extra CMake arguments when building Zorba:
+
+-D "CCLIENT_INCLUDE=path_to_imap-2007e\c-client"
+-D "CCLIENT_LIBRARY=path_to_imap-2007e\c-client\release\cclient.lib"
+

=== added directory 'src/com/zorba-xquery/www/modules/email/cclient'
=== added file 'src/com/zorba-xquery/www/modules/email/cclient/email_exception.cpp'
--- src/com/zorba-xquery/www/modules/email/cclient/email_exception.cpp	1970-01-01 00:00:00 +0000
+++ src/com/zorba-xquery/www/modules/email/cclient/email_exception.cpp	2014-04-30 23:07:12 +0000
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2006-2008 The FLWOR Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "email_exception.h"
+
+
+namespace zorba { namespace emailmodule {
+
+EmailException::EmailException(
+  const std::string& aLocalName,
+  const std::string& msg) throw()
+  : theLocalName(aLocalName), theMessage(msg)
+{
+}
+
+EmailException::~EmailException() throw()
+{
+}
+
+const char*
+EmailException::what() const throw()
+{
+  return theMessage.c_str();
+}
+
+const std::string&
+EmailException::get_message() const
+{
+  return theMessage;
+}
+
+const std::string&
+EmailException::get_localname() const
+{
+  return theLocalName;
+}
+
+} // namespace emailmodule
+} // namespace zorba

=== added file 'src/com/zorba-xquery/www/modules/email/cclient/email_exception.h'
--- src/com/zorba-xquery/www/modules/email/cclient/email_exception.h	1970-01-01 00:00:00 +0000
+++ src/com/zorba-xquery/www/modules/email/cclient/email_exception.h	2014-04-30 23:07:12 +0000
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2006-2008 The FLWOR Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ZORBA_EMAILMODULE_EMAILEXCEPTION_H
+#define ZORBA_EMAILMODULE_EMAILEXCEPTION_H
+
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+#include "c-client.h"
+#include <string>
+#undef max
+#include <list>
+#include <vector>
+#include <exception>
+#include <sstream>
+
+namespace zorba { namespace emailmodule {
+
+class EmailException : std::exception
+{
+  public:
+    explicit EmailException(
+      const std::string& aLocalName,
+      const std::string& message) throw();
+  
+    virtual ~EmailException() throw();
+
+    virtual const char*
+    what() const throw();
+
+    const std::string&
+    get_message() const;
+
+    const std::string&
+    get_localname() const;
+
+  private:
+    std::string theLocalName;
+    std::string theMessage;
+};
+    
+} // namespace emailmodule
+} // namespace zorba
+
+#endif // ZORBA_EMAILMODULE_EMAILEXCEPTION_H

=== added file 'src/com/zorba-xquery/www/modules/email/cclient/imap_client.cpp'
--- src/com/zorba-xquery/www/modules/email/cclient/imap_client.cpp	1970-01-01 00:00:00 +0000
+++ src/com/zorba-xquery/www/modules/email/cclient/imap_client.cpp	2014-04-30 23:07:12 +0000
@@ -0,0 +1,938 @@
+/*
+ * Copyright 2006-2008 The FLWOR Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "imap_client.h"
+
+#include <stdio.h>
+#include <iostream>
+#include <sstream>
+#include <vector>
+
+#include "email_exception.h"
+
+#ifndef WIN32
+#pragma GCC diagnostic ignored "-Wwrite-strings"
+#endif
+
+
+namespace zorba { namespace emailmodule {
+  
+  // functions for smtp support
+  
+  bool
+  ImapClient::send(const std::string& aHost,
+                   const std::string& aUsername,
+                   const std::string& aPassword,
+                   ENVELOPE* aEnvelope,
+                   BODY* aBody,
+                   std::stringstream& aDiagnostics) {
+    
+    
+    
+    setUserName(aUsername);
+    setPassword(aPassword); 
+    
+    std::stringstream out;
+    char tmp[MAILTMPLEN];
+    SENDSTREAM *smtp_stream = NIL;
+    bool res = false;
+    
+    char *hostlist[2];
+    hostlist[0] = const_cast<char*>(aHost.c_str());
+    hostlist[1] = NIL;
+    
+#include "linkage.c"
+#if MACOS
+    {
+      size_t *base = (size_t *) 0x000908;
+      // increase stack size on a Mac
+      SetApplLimit ((Ptr) (*base - (size_t) 65535L));
+    }
+#endif
+    
+    out << "Sending..." << std::endl;
+    smtp_stream = smtp_open (hostlist,0);
+    if ( smtp_stream ) {
+      if ( smtp_stream->replycode >= 400 ) {
+        out << smtp_stream->reply << std::endl;
+      }
+      else {
+        sprintf (tmp, "MAIL");
+        res = smtp_mail(smtp_stream, tmp, aEnvelope, aBody) != 0;
+        if (res) {
+          out << "Ok.";
+        } else {
+          out << "Failed.";
+          out << std::endl << "Reply: " << smtp_stream->reply;
+          // Check if it was a problem with the reciptients
+          ADDRESS* lAdresses[4] = {aEnvelope->from, aEnvelope->to, aEnvelope->cc, aEnvelope->bcc};
+          for (int i = 0; i < 4; ++i) {
+            ADDRESS* lAddress = lAdresses[i];
+            while (lAddress) {
+              if (lAddress->error) {
+                out << std::endl << "\tProblem with address " << lAddress->mailbox << "@" << lAddress->host << ": " << aEnvelope->to->error;
+              }
+              lAddress = lAddress->next;
+            }
+          }
+        }
+        smtp_close(smtp_stream);
+      } 
+    } else { 
+      out << "Opening connection to " << aHost << " failed." << std::endl;
+    }
+    
+    aDiagnostics << out.str();
+    return res;
+    
+    
+  }
+  
+  
+  // functions for imap support
+  void
+  ImapClient::setUserName(const std::string& usr) {
+    theUserName = usr; 
+  }
+  
+  void
+  ImapClient::setPassword(const std::string& pwd) {
+    thePassword = pwd;
+  }
+  
+  std::string 
+  ImapClient::getUserName() {
+    return theUserName;
+  }
+  
+  std::string
+  ImapClient::getPassword() {
+    return thePassword;
+  }
+  
+  MAILSTREAM* 
+  ImapClient::getMailStream(const std::string& aHost,
+                            const std::string& aUsername,
+                            const std::string& aPassword,                                
+                            const std::string& aMailbox,
+                            const bool aFullOpen) {
+    std::string lHostAndMailbox = "{" + aHost + "}" + aMailbox; 
+    
+    // check if there is a mailstream that is already open with the same parameters, if true then take it (this is the ideal case)
+    
+    int lNumberOfKnownHosts = (int)theHosts.size();
+    std::list<Host>::iterator allHostsIterator;
+    for (allHostsIterator = theHosts.begin(); allHostsIterator != theHosts.end(); allHostsIterator++) {  
+      if (((*allHostsIterator).lMailStream) &&
+          ((*allHostsIterator).lUsername.compare(aUsername) == 0) &&
+          ((*allHostsIterator).lPassword.compare(aPassword) == 0) &&
+          ((*allHostsIterator).lHostNameWithMailbox.compare(lHostAndMailbox) == 0)) {
+        
+        // if we already have mailstream but it is not full open yet, then open it again, this time full
+        if ((*allHostsIterator).lIsFullOpen == false && aFullOpen == true) {
+          setUserName((*allHostsIterator).lUsername);
+          setPassword((*allHostsIterator).lPassword);
+          mail_open((*allHostsIterator).lMailStream, const_cast<char*>(lHostAndMailbox.c_str()), NIL);
+          (*allHostsIterator).lIsFullOpen = true;
+          
+        }
+        return (*allHostsIterator).lMailStream;
+      }
+    }
+    // if we found an existing mailstream, then everything is ok, if not we have to make a new one
+    Host lNewHost;
+    lNewHost.lUsername = aUsername;
+    lNewHost.lPassword = aPassword;
+    lNewHost.lHostNameWithMailbox = lHostAndMailbox;
+    lNewHost.lIsFullOpen = aFullOpen;
+    // if we already have more then 7 open mailstreams, close the last one to make place 
+    if (lNumberOfKnownHosts == 7) { 
+      Host lToDelete = theHosts.back();
+      theHosts.pop_back();
+      mail_close(lToDelete.lMailStream);
+    } 
+    
+    setUserName(aUsername);
+    setPassword(aPassword);
+    
+    lNewHost.lMailStream = mail_open(NIL, const_cast<char*>(lHostAndMailbox.c_str()), (aFullOpen ? NIL : OP_HALFOPEN));
+    theHosts.push_front(lNewHost);
+    
+    checkMailStream(lNewHost.lMailStream);
+    return lNewHost.lMailStream;
+  }
+  
+  
+  void 
+  ImapClient::status (const std::string& aHost, 
+                      const std::string& aUsername, 
+                      const std::string& aPassword, 
+                      const std::string& aMailbox) 
+  {
+#include "linkage.c"
+    std::string lHostAndMailbox = "{" + aHost + "}" ;
+    MAILSTREAM* lSource = getMailStream(aHost, aUsername, aPassword, aMailbox, false);
+    mail_status (lSource, const_cast<char*>(lHostAndMailbox.c_str()), SA_MESSAGES | SA_RECENT | SA_UNSEEN | SA_UIDNEXT | SA_UIDVALIDITY);
+  }
+  
+  bool
+  ImapClient::create (const std::string& aHost, 
+                      const std::string& aUsername, 
+                      const std::string& aPassword, 
+                      const std::string& aMailbox) {
+    
+#include "linkage.c"
+    MAILSTREAM* lSource = getMailStream(aHost, aUsername, aPassword, aMailbox, false); 
+    std::string lFullName = "{" + aHost + "}" + aMailbox; 
+    return (mail_create (lSource, const_cast<char*>(lFullName.c_str())) == T);
+  }
+  
+  
+  bool
+  ImapClient::delete_mailbox (const std::string& aHost, 
+                              const std::string& aUsername, 
+                              const std::string& aPassword, 
+                              const  std::string& aMailbox) {
+    
+#include "linkage.c"
+    MAILSTREAM *lSource = getMailStream(aHost, aUsername, aPassword, aMailbox, false);
+    std::string lFullName = "{" + aHost + "}" + aMailbox;
+    return (mail_delete(lSource, const_cast<char*>(lFullName.c_str())) == T);
+  }
+  
+  bool 
+  ImapClient::rename (const std::string& aHost, 
+                      const std::string& aUsername, 
+                      const  std::string& aPassword, 
+                      const std::string& aFromMailbox, 
+                      const std::string& aToMailbox) {
+    
+#include "linkage.c"
+    MAILSTREAM* lSource = getMailStream(aHost, aUsername, aPassword, "", false);
+    std::string lHost = "{" + aHost + "}"; 
+    std::string lFullNameOld = lHost + aFromMailbox;
+    std::string lFullNameNew = lHost + aToMailbox;
+    return (mail_rename(lSource, const_cast<char*>(lFullNameOld.c_str()), const_cast<char*>( lFullNameNew.c_str())) == T);
+  } 
+  
+  bool 
+  ImapClient::subscription(const std::string& aHost,  
+                           const std::string& aUsername, 
+                           const std::string& aPassword, 
+                           const std::string& aMailbox, 
+                           bool subscribe) {
+    
+#include "linkage.c"
+    std::string lHost = "{" + aHost + "}";
+    MAILSTREAM* lSource = getMailStream(aHost, aUsername, aPassword, aMailbox, false); 
+    std::string lFullName = lHost + aMailbox;
+    if (subscribe) {
+      return (mail_subscribe(lSource, const_cast<char*>(lFullName.c_str())) == T);
+    } else {
+      return (mail_unsubscribe(lSource, const_cast<char*>(lFullName.c_str())) == T);
+    }
+  }
+  
+  
+  bool
+  ImapClient::expunge(const std::string& aHost, 
+                      const std::string& aUsername, 
+                      const std::string& aPassword, 
+                      const std::string& aMailbox) {
+    
+#include "linkage.c"
+    std::string lHost = "{" + aHost + "}" + aMailbox;
+    MAILSTREAM* lSource = getMailStream(aHost, aUsername, aPassword, aMailbox, true); 
+    if (lSource) {  mail_expunge(lSource); }
+    return true;
+  }
+  
+  
+  std::vector<std::string> 
+  ImapClient::list(const std::string& aHost, 
+                   const std::string& aUsername, 
+                   const std::string& aPassword, 
+                   const std::string& aReferencePath, 
+                   const std::string& aPattern, 
+                   bool aOnlySuscribed) {
+    
+#include "linkage.c"
+    /* IMPORTANT: make sure that the vector of listed mailboxes is empty! */
+    theListedMailboxes.clear();
+    
+    std::string lHost = "{" + aHost + "}";
+    MAILSTREAM* lSource = getMailStream(aHost, aUsername, aPassword, "", false); 
+    std::string lFullPath = lHost + aReferencePath;
+    if (aOnlySuscribed) {
+      mail_lsub(lSource, const_cast<char*>(lFullPath.c_str()), const_cast<char*>(aPattern.c_str()));
+    } else {
+      mail_list(lSource,  const_cast<char*>(lFullPath.c_str()), const_cast<char*>(aPattern.c_str()));
+    }
+    // theListedMailbox is filled through the mm_list or mm_listsub callback functions
+    return theListedMailboxes;
+  }  
+  
+  bool 
+  ImapClient::copy(const std::string& aHost, 
+                   const std::string& aUserName, 
+                   const std::string& aPassword, 
+                   const std::string& aMailboxFrom, 
+                   const std::string& aMailboxTo, 
+                   const std::string& aMessageNumbers, 
+                   bool aUid,   
+                   bool aCopy) {
+    
+#include "linkage.c"
+    
+    std::string lHost = "{" + aHost + "}" + aMailboxFrom;
+    MAILSTREAM* lSource = getMailStream(aHost, aUserName, aPassword, aMailboxFrom, true); 
+    long  lLongResult =  mail_copy_full(lSource,  const_cast<char*>(aMessageNumbers.c_str()),  const_cast<char*>(aMailboxTo.c_str()), (aUid ? SE_UID : NIL) | (aCopy ? NIL : CP_MOVE));
+    return (lLongResult == T);
+  }
+  
+  std::vector<long>
+  ImapClient::search(const std::string& aHost, 
+                     const std::string& aUsername, 
+                     const std::string& aPassword, 
+                     const std::string& aMailbox, 
+                     const std::string& aCriteria, 
+                     bool aUid) {
+    
+#include "linkage.c"
+    
+    /* IMPORTANT: make sure that the vector of found sequence numbers is empty! */
+    theFoundSequenceNumbers.clear();
+    
+    MAILSTREAM* lSource = getMailStream(aHost, aUsername, aPassword, aMailbox, true);
+    checkMailStream(lSource);
+    mail_ping(lSource);
+    
+    
+    /* First, tokenize the criteria so that we can work on it */
+    std::stringstream lToTokenize(aCriteria);
+    std::string lBuffer;
+    std::vector<std::string> lTokens;
+    
+    SEARCHPGM * lSearchProgram;
+    while(lToTokenize >> lBuffer) {
+      lTokens.push_back(lBuffer);
+    }
+    lSearchProgram = search_criteria(lTokens);
+    
+    mail_search_full(lSource, NIL,  lSearchProgram, (aUid ? SE_UID : NIL) | SE_NOPREFETCH); 
+    /* clean up, don't leave a mess */
+    mail_free_searchpgm(&lSearchProgram); 
+    return theFoundSequenceNumbers;
+  }
+  
+  ENVELOPE * 
+  ImapClient::fetchEnvelope(const std::string& aHost, 
+                            const std::string& aUsername, 
+                            const std::string& aPassword, 
+                            const std::string& aMailbox, 
+                            unsigned long aMessageNumber,
+                            std::vector<int>& aFlagsVector,
+                            const bool aUid) 
+  {
+#include "linkage.c"
+    MAILSTREAM* lSource = getMailStream(aHost, aUsername, aPassword, aMailbox, true); 
+    
+    if (aUid) {
+      aMessageNumber = mail_msgno(lSource, aMessageNumber);
+    }
+    
+    ENVELOPE* lResult = mail_fetchenvelope(lSource, aMessageNumber);
+    
+    if (!lResult) {
+      throw EmailException("WRONG_ID", "Could not get message - wrong message id.");
+    }
+    
+    
+    MESSAGECACHE* lCache = mail_elt(lSource, aMessageNumber);
+    
+    if (lCache->seen == 1) {
+      aFlagsVector[0] = 1;
+    }
+    if (lCache->deleted == 1) {
+      aFlagsVector[1] = 1;
+    }
+    if (lCache->flagged == 1) {
+      aFlagsVector[2] = 1;
+    }
+    if (lCache->answered == 1) {
+      aFlagsVector[3] = 1;
+    }
+    if (lCache->draft == 1) {
+      aFlagsVector[4] = 1;
+    }
+    
+    return  lResult;
+    
+  }
+  
+std::string
+ImapClient::fetchSubject(
+  const std::string& aHost,
+  const std::string& aUserName,
+  const std::string& aPassword,
+  const std::string& aMailbox,
+  const unsigned long aMessageNumber)
+{
+#include "linkage.c"
+    
+  std::string lHost = "{" + aHost + "}" + aMailbox; 
+  MAILSTREAM* lSource = getMailStream(aHost, aUserName, aPassword, aMailbox, true); 
+    
+  char lResult[256];
+  mail_fetchsubject(lResult, lSource, aMessageNumber, (unsigned long)255);
+  return std::string(lResult);
+}
+  
+  
+  
+  std::string
+  ImapClient::fetchFrom(const std::string& aHost,
+                        const std::string& aUserName,
+                        const std::string& aPassword,
+                        const std::string& aMailbox,
+                        const unsigned long aMessageNumber) {
+    
+#include "linkage.c"
+    
+    MAILSTREAM* lSource = getMailStream(aHost, aUserName, aPassword, aMailbox, true); 
+    
+    char lResult[256];
+    mail_fetchsubject(lResult, lSource, aMessageNumber, (unsigned long)255);
+    return std::string(lResult);
+  }
+  
+  long                            
+  ImapClient::convertNumber(const std::string& aHost,
+                            const std::string& aUserName,
+                            const std::string& aPassword,
+                            const std::string& aMailbox,
+                            const unsigned long aMessageNumber,
+                            const bool aUid) {
+    
+#include "linkage.c"
+    
+    MAILSTREAM* lSource = getMailStream(aHost, aUserName, aPassword, aMailbox, true); 
+    
+    if (aUid) {
+      return mail_uid(lSource, aMessageNumber);
+    } else {
+      return mail_msgno(lSource, aMessageNumber);
+    }
+    
+    
+  }
+  
+  ENVELOPE* 
+  ImapClient::fetchStructure(const std::string& aHost, 
+                             const std::string& aUserName, 
+                             const std::string& aPassword, 
+                             const std::string& aMailbox, 
+                             BODY** aBody,  
+                             unsigned long aMessageNumber, 
+                             bool aUid,
+                             std::vector<int>& aFlagsVector) 
+  {
+#include "linkage.c"
+    *aBody = mail_newbody(); 
+    MAILSTREAM* lSource = getMailStream(aHost, aUserName, aPassword, aMailbox, true);    
+    
+    ENVELOPE * lResult = mail_fetchstructure_full (lSource, aMessageNumber, aBody, (aUid ? FT_UID : NIL));
+    
+    if (!lResult) {
+      throw EmailException("WRONG_ID", "Could not get message - wrong message id.");
+    }
+    
+    if (aUid) {
+      aMessageNumber = mail_msgno(lSource, aMessageNumber);
+    }
+    
+    MESSAGECACHE* lCache = mail_elt(lSource, aMessageNumber);
+    
+    if (lCache->seen == 1) {
+      aFlagsVector[0] = 1;
+    }
+    if (lCache->deleted == 1) {
+      aFlagsVector[1] = 1;
+    }
+    if (lCache->flagged == 1) {
+      aFlagsVector[2] = 1;
+    }
+    if (lCache->answered == 1) {
+      aFlagsVector[3] = 1;
+    }
+    if (lCache->draft == 1) {
+      aFlagsVector[4] = 1;
+    }
+    
+    return lResult;
+    
+  }
+  
+  std::string 
+  ImapClient::fetchText(const std::string& aHost, 
+                        const std::string& aUserName,
+                        const std::string& aPassword,
+                        const std::string& aMailbox,
+                        unsigned long aMessageNumber,
+                        bool aUid)
+  {
+#include "linkage.c"
+    
+    MAILSTREAM* lSource = getMailStream(aHost, aUserName, aPassword, aMailbox, true); 
+    unsigned long lLenght;
+    return std::string(mail_fetchtext_full(lSource, aMessageNumber, &lLenght, (aUid ? FT_UID : NIL))); 
+  } 
+  
+  
+  void 
+  ImapClient::fetchFlags(const std::string& aHost,
+                         const std::string& aUserName,
+                         const std::string& aPassword,
+                         const std::string& aMailbox,
+                         unsigned long aMessageNumber,
+                         std::vector<int>& aFlagsVector,
+                         const bool aUid) {
+    
+#include "linkage.c"
+    
+    
+    MAILSTREAM* lSource = getMailStream(aHost, aUserName, aPassword, aMailbox, true);
+    // convert aMessageNumber to message sequence number if necessary     
+    std::string lSequenceNumber;
+    std::stringstream lConverter;
+    lConverter << aMessageNumber;
+    lConverter >> lSequenceNumber; 
+    char* lSequence = const_cast<char*>(lSequenceNumber.c_str());
+    
+    
+    
+    // update cache for this message (could have changed because of a call to setFlags) 
+    mail_fetchflags_full(lSource, lSequence, (aUid ? FT_UID : NIL));  
+    
+    if (aUid) {
+      aMessageNumber = mail_msgno(lSource, aMessageNumber); 
+    }     
+    
+    MESSAGECACHE* lCache = mail_elt(lSource, aMessageNumber);
+    
+    if (lCache->seen == 1) {
+      aFlagsVector[0] = 1;
+    }
+    if (lCache->deleted == 1) {
+      aFlagsVector[1] = 1;
+    }
+    if (lCache->flagged == 1) {
+      aFlagsVector[2] = 1;
+    } 
+    if (lCache->answered == 1) {
+      aFlagsVector[3] = 1;
+    }
+    if (lCache->draft == 1) {
+      aFlagsVector[4] = 1;
+    }
+    
+  }
+  
+  void
+  ImapClient::setFlags(const std::string& aHost,
+                       const std::string& aUserName,
+                       const std::string& aPassword,
+                       const std::string& aMailbox,
+                       const unsigned long aMessageNumber,
+                       const std::vector<int>& aFlagsVector,
+                       const bool aUid) {
+    
+    
+#include "linkage.c"
+    MAILSTREAM* lSource = getMailStream(aHost, aUserName, aPassword, aMailbox, true);
+    std::string lSequenceNumber;
+    std::stringstream lConverter;
+    lConverter << aMessageNumber;
+    lConverter >> lSequenceNumber;
+    char* lSequence = const_cast<char*>(lSequenceNumber.c_str());
+    
+    if (aFlagsVector[0] == 1) {
+      mail_setflag_full(lSource, lSequence, "\\Seen",  (aUid ? ST_UID : NIL) );
+    } else {
+      mail_clearflag_full(lSource, lSequence, "\\Seen",  (aUid ? ST_UID : NIL ) );
+    }
+    
+    if (aFlagsVector[1] == 1) {
+      mail_setflag_full(lSource, lSequence, "\\Deleted",  (aUid ? ST_UID : NIL)); 
+    } else {
+      mail_clearflag_full(lSource, lSequence, "\\Deleted",  (aUid ? ST_UID : NIL)); 
+    }
+    if (aFlagsVector[2] == 1) { 
+      mail_setflag_full(lSource, lSequence, "\\Flagged",  (aUid ? ST_UID : NIL)); 
+    } else {
+      mail_clearflag_full(lSource, lSequence, "\\Flagged",  (aUid ? ST_UID : NIL)); 
+    } 
+    
+    if (aFlagsVector[3] == 1) {
+      mail_setflag_full(lSource, lSequence, "\\Answered",  (aUid ? ST_UID : NIL)); 
+    } else {
+      mail_clearflag_full(lSource, lSequence, "\\Answered",  (aUid ? ST_UID : NIL)); 
+    }
+    if (aFlagsVector[4] == 1) {
+      mail_setflag_full(lSource, lSequence, "\\Draft",  (aUid ? ST_UID : NIL)); 
+    } else {
+      mail_clearflag_full(lSource, lSequence, "\\Draft",  (aUid ? ST_UID : NIL)); 
+    }
+  }
+  
+  std::string
+  ImapClient::fetchBodyFull(const std::string& aHost,
+                            const std::string& aUserName,
+                            const std::string& aPassword,
+                            const std::string& aMailbox,
+                            const unsigned long aMessageNumber,
+                            const std::string& aSection,
+                            const bool aUid) 
+  {
+#include "linkage.c"
+    MAILSTREAM* lSource = getMailStream(aHost, aUserName, aPassword, aMailbox, true); 
+    unsigned long lLenght;
+    // convert section int into char
+    return std::string(mail_fetchbody_full(lSource, aMessageNumber, const_cast<char*>(aSection.c_str()), &lLenght, (aUid ? FT_UID : NIL)));
+    
+  } 
+  
+  SEARCHPGM*
+  ImapClient::search_criteria(std::vector<std::string> aCriteria) {
+    SEARCHPGM *lSearchProgram = NIL;
+    
+    /* initializing the search program */
+    lSearchProgram= mail_newsearchpgm ();
+    
+    /* Now, we iterate through the whole vector containing the search critera, building our search program */
+    for (std::vector<std::string>::iterator lIterator = aCriteria.begin(); lIterator != aCriteria.end(); ++lIterator) {
+      if (*lIterator == "ALL") {
+        /* do nothing ... */
+      } else if (*lIterator == "ANSWERED") {
+        lSearchProgram->answered = T;
+      } else if (*lIterator == "BCC") {
+        char * lNext = getNextStringAsChar(++lIterator); 
+        mail_criteria_string (&lSearchProgram->bcc, &lNext);
+      } else if (*lIterator == "BEFORE") {
+        char* lNext = getNextStringAsChar(++lIterator); 
+        mail_criteria_date(&lSearchProgram->before, &lNext);
+      } else if (*lIterator == "BODY") {
+        char* lNext = getNextStringAsChar(++lIterator); 
+        mail_criteria_string(&lSearchProgram->body, &lNext);
+      } else if (*lIterator == "CC") {
+        char* lNext = getNextStringAsChar(++lIterator); 
+        mail_criteria_string(&lSearchProgram->cc, &lNext);
+      } else if (*lIterator == "DELETED") {
+        lSearchProgram->deleted = T;
+      } else if (*lIterator == "DRAFT") {
+        lSearchProgram->draft = T;
+      } else if (*lIterator == "FLAGGED") {
+        lSearchProgram->flagged = T;
+      } else if (*lIterator == "FROM") {
+        char* lNext = getNextStringAsChar(++lIterator); 
+        mail_criteria_string(&lSearchProgram->from, &lNext);
+      } else if (*lIterator == "HEADER") {
+        char *lHeaderField = getNextStringAsChar(++lIterator);
+        char *lHeaderContent = getNextStringAsChar(++lIterator);  
+        SEARCHHEADER* lSearchHeader = mail_newsearchheader(lHeaderField, lHeaderContent);
+        if (lSearchProgram->header) {
+          lSearchProgram->header->next = lSearchHeader;
+        } else {
+          lSearchProgram->header = lSearchHeader;
+        }  
+      } else if (*lIterator == "KEYWORD") {
+        char * lNext = getNextStringAsChar(++lIterator); 
+        mail_criteria_string(&lSearchProgram->keyword, &lNext);
+      } else if (*lIterator == "LARGER") {
+        lIterator++;
+        // get the unsigned long value that should follow the Keyword LARGER
+        std::stringstream lLargerValueStream;
+        lLargerValueStream << (*lIterator).c_str();
+        unsigned long lLargerValue; 
+        lLargerValueStream >> lLargerValue;
+        lSearchProgram->larger = lLargerValue;
+      } else if (*lIterator == "NEW") {
+        // according to the specification, this is equivalent to recent unseen
+        lSearchProgram->recent = T;
+        lSearchProgram->unseen = T;
+      }  else if (*lIterator == "OLD") {
+        lSearchProgram->old = T;
+      } else if (*lIterator == "ON") {
+        char * lNext = getNextStringAsChar(++lIterator); 
+        mail_criteria_date(&lSearchProgram->on, &lNext);
+      } else if (*lIterator == "RECENT") {
+        lSearchProgram->recent = T;
+      } else if (*lIterator == "SEEN") {
+        lSearchProgram->seen = T;
+      } else if (*lIterator == "SENTBEFORE") {
+        char * lNext = getNextStringAsChar(++lIterator); 
+        mail_criteria_date(&lSearchProgram->sentbefore, &lNext);
+      } else if (*lIterator == "SENTON") {
+        char *lNext = getNextStringAsChar(lIterator);
+        mail_criteria_date(&lSearchProgram->senton, &lNext);
+      } else if (*lIterator == "SENTSINCE") {
+        char *lNext = getNextStringAsChar(++lIterator); 
+        mail_criteria_date(&lSearchProgram->sentsince, &lNext);
+      } else if (*lIterator == "SMALLER") {
+        lIterator++;
+        std::stringstream lSmallerValueStream;
+        lSmallerValueStream << (*lIterator).c_str();
+        unsigned long lSmallerValue;
+        lSmallerValueStream >> lSmallerValue;
+        lSearchProgram->smaller = lSmallerValue;
+      } else if (*lIterator == "SUBJECT") {
+        char *lNext = getNextStringAsChar(++lIterator);
+        mail_criteria_string(&lSearchProgram->subject, &lNext);
+      } else if (*lIterator == "TEXT") {
+        char *lNext = getNextStringAsChar(++lIterator); 
+        mail_criteria_string(&lSearchProgram->text, &lNext);
+      } else if (*lIterator == "TO") {
+        char *lNext = getNextStringAsChar(++lIterator); 
+        mail_criteria_string(&lSearchProgram->to, &lNext);
+      } else if (*lIterator == "UNANSWERED") {
+        lSearchProgram->unanswered = T;
+      } else if (*lIterator == "UNDELETED") {
+        lSearchProgram->undeleted = T;
+      } else if (*lIterator == "UNDRAFT") {
+        lSearchProgram->undraft = T;
+      } else if (*lIterator == "UNFLAGGED") {
+        lSearchProgram->unflagged = T;
+      } else if (*lIterator == "UNKEYWORD") {
+        char *lNext = getNextStringAsChar(++lIterator); 
+        mail_criteria_string(&lSearchProgram->unkeyword, &lNext);
+      } else if (*lIterator == "UNSEEN") {
+        lSearchProgram->unseen = T;
+      } else if (*lIterator == "NOT") {
+        std::vector<std::string> lNotVector;
+        std::string lNextWord = *(++lIterator);
+        // if next word is a keyword that needs a parameter
+        lNotVector.push_back(lNextWord);
+        if (!isSingleKeyword(lNextWord)) {
+          // pass parameter
+          lNotVector.push_back(*(++lIterator));
+        }
+        SEARCHPGM* lNotted = search_criteria(lNotVector);        
+        SEARCHPGMLIST* lNotList = mail_newsearchpgmlist (); 
+        lNotList->pgm = lNotted;
+        lSearchProgram->not = lNotList;
+      } else if (*lIterator == "OR") {
+        // Make all up to the or be the first search_program, then or the rest ...
+        
+        std::vector<std::string> lOrVector(++lIterator, aCriteria.end());
+        SEARCHPGM* lOredProgram = search_criteria(lOrVector);
+        
+        // or the search_program we have constructed so far with the search_program constructed from the rest of the strings 
+        SEARCHOR* lOr = mail_newsearchor(); 
+        lOr->first = lOredProgram;     
+        lOr->second = lSearchProgram;
+        
+        // Make a new search program that only contains the OR'ed search_programs and assign the pointer we are going to return to it 
+        SEARCHPGM* lNewSearchProgramm = mail_newsearchpgm();
+        lNewSearchProgramm->or = lOr;
+        lSearchProgram = lNewSearchProgramm; 
+        // stop here, at least for the left-hand part of the OR. 
+        break; 
+        
+      } else {
+        std::string lError = "Unknown keyword in IMAP search: " + *lIterator; 
+        // if the word is not known ... throw an error through mm_log 
+        mm_log((char *) lError.c_str(), ERROR);  
+      }  
+    }
+    return lSearchProgram;
+  }
+  
+  char * ImapClient::getNextStringAsChar(std::vector<std::string>::iterator aIterator) {
+    return (char*) (*aIterator).c_str();
+  }  
+  
+  bool 
+  ImapClient::isSingleKeyword(const std::string& aKey) {
+    if (aKey == "UNSEEN" || aKey == "UNANSWERED" || aKey == "UNDELETED" || aKey == "UNDRAFT" || aKey == "UNFLAGGED" || aKey == "DELETED" || aKey == "DRAFT" ||
+        aKey == "FLAGGED" || aKey == "NEW" || aKey == "OLD" || aKey == "RECENT" || aKey == "SEEN" || aKey == "ANSWERED") {
+      return true;
+    }
+    return false;
+  }
+  
+  void 
+  ImapClient::setStatus(unsigned long aMessages, unsigned long aRecent, unsigned long aUnseen, unsigned long aUIDNext, unsigned long aUIDValidity) {
+    theMessages = aMessages;
+    theRecent = aRecent;
+    theUnseen = aUnseen;
+    theUIDNext = aUIDNext;
+    theUIDValidity = aUIDValidity;
+  }
+  
+  
+  void
+  ImapClient::getStatus(unsigned long* aMessages, unsigned long* aRecent, unsigned long* aUnseen, unsigned long* aUIDNext, unsigned long* aUIDValidity) {
+    
+    *aMessages = theMessages;
+    *aRecent = theRecent;
+    *aUnseen = theUnseen;
+    *aUIDNext = theUIDNext;
+    *aUIDValidity = theUIDValidity;
+    
+    
+  }
+  
+  void
+  ImapClient::addListedMailbox(const std::string& aListedMail) {
+    theListedMailboxes.push_back(aListedMail);
+  } 
+  
+  
+  std::string 
+  ImapClient::getError() {
+    // will not see an old error  
+    
+    std::string lTempError(theErrorMessage.str());
+    theErrorMessage.clear();
+    return lTempError;
+  }
+  
+  
+  
+  void 
+  ImapClient::addError(const std::string& aMessage) {
+    theErrorMessage << aMessage << std::endl;
+  }
+  
+  void ImapClient::addLogEntry(std::string const &aLogEntry)
+  {
+    theLog << aLogEntry << std::endl;
+  }
+  
+  void 
+  ImapClient::addFoundSequenceNumber(long aSequenceNumber) {
+    theFoundSequenceNumbers.push_back(aSequenceNumber);
+  }
+  
+  void
+  ImapClient::checkMailStream(MAILSTREAM *aStream)
+  {
+    if (!aStream) {
+      std::stringstream lMessage;
+      lMessage << "Could not open mail stream. " << theErrorMessage.str() << "." << std::endl;
+      theLog.clear();
+      theErrorMessage.clear();
+      throw EmailException("CONNECTION_ERROR", lMessage.str());
+    }
+  }
+  
+  
+} /* emailmodule */ } /* zorba */
+
+
+
+void mm_searched (MAILSTREAM *stream,unsigned long msgno) {
+  zorba::emailmodule::ImapClient::Instance().addFoundSequenceNumber(msgno);
+}
+void mm_exists (MAILSTREAM *stream,unsigned long number) {}
+void mm_expunged (MAILSTREAM *stream,unsigned long number) {}
+
+/*
+ * Callback for when mail_fetchflags(_full) is called.
+ */ 
+void mm_flags (MAILSTREAM *stream,unsigned long number) {
+}
+
+/* Callback for when mail_list or mail_listsub are called ... */
+void mm_list (MAILSTREAM *stream,int delimiter,char *mailbox, long attributes) {
+  if (!(attributes & LATT_NOSELECT) && *mailbox)  {
+    zorba::emailmodule::ImapClient::Instance().addListedMailbox(std::string(mailbox)); 
+  }  
+}
+void mm_lsub (MAILSTREAM *stream,int delimiter,char *mailbox,long attributes) {
+  if (!(attributes & LATT_NOSELECT) && *mailbox)  {
+    zorba::emailmodule::ImapClient::Instance().addListedMailbox(std::string(mailbox));
+  }
+}
+
+void mm_critical (MAILSTREAM *stream) {}
+void mm_nocritical (MAILSTREAM *stream) {}
+long mm_diskerror (MAILSTREAM *stream,long errcode,long serious) {return NIL;}
+
+
+void mm_notify (MAILSTREAM *stream,char *string,long errflg) {}
+
+
+
+void mm_status (MAILSTREAM *stream,char *mailbox,MAILSTATUS *status) {
+  zorba::emailmodule::ImapClient::Instance().setStatus(status->messages, status->recent, status->unseen, status->uidnext, status->uidvalidity);
+}   
+
+/* Log an event for the user to see
+ * Accepts: string to log
+ *          error flag
+ */
+void mm_log (char *string,long errflg)
+{
+  
+  switch ((short) errflg) {
+    case NIL:
+      
+    case PARSE:
+    case WARN:
+      zorba::emailmodule::ImapClient::Instance().addLogEntry(string);
+      break;
+    case ERROR:
+      zorba::emailmodule::ImapClient::Instance().addError(string);
+      break;
+  }
+}
+
+/* Log an event to debugging telemetry
+ * Accepts: string to log
+ */
+void mm_dlog (char *string)
+{
+  std::cout << string << '\n';
+}
+
+/* Get user name and password for this host
+ * Accepts: parse of network mailbox name
+ *          where to return user name
+ *          where to return password
+ *          trial count
+ */
+void mm_login (NETMBX *mb,char *user,char *pwd,long trial)
+{
+  std::string lUser = zorba::emailmodule::ImapClient::Instance().getUserName().c_str();
+  std::string lPassword = zorba::emailmodule::ImapClient::Instance().getPassword().c_str();
+  
+  strcpy(user, const_cast<char*>(lUser.c_str()));
+  strcpy(pwd, const_cast<char*>(lPassword.c_str()));
+}
+
+/* Log a fatal error event
+ * Accepts: string to log
+ */
+void mm_fatal (char *string)
+{
+  printf ("?%s\n",string);
+}
+
+
+#ifndef WIN32
+#pragma GCC diagnostic warning "-Wwrite-strings"
+#endif

=== added file 'src/com/zorba-xquery/www/modules/email/cclient/imap_client.h'
--- src/com/zorba-xquery/www/modules/email/cclient/imap_client.h	1970-01-01 00:00:00 +0000
+++ src/com/zorba-xquery/www/modules/email/cclient/imap_client.h	2014-04-30 23:07:12 +0000
@@ -0,0 +1,294 @@
+/*
+ * Copyright 2006-2008 The FLWOR Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ZORBA_EMAIL_IMAP_CLIENT_H
+#define ZORBA_EMAIL_IMAP_CLIENT_H 
+
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <c-client.h>
+#undef max
+
+#include <string>
+#include <list>
+#include <vector>
+#include <exception>
+#include <sstream>
+
+
+namespace zorba { namespace emailmodule {
+
+    class ImapClient
+    {
+    public:
+      static ImapClient& Instance()
+      {
+        static ImapClient lInstance;
+        return lInstance;
+      }
+       
+      
+      
+      bool
+      send(const std::string& aHost,
+           const std::string& aUsername,
+           const std::string& aPassword,
+           ENVELOPE* aEnvelope,
+           BODY* aBody,
+           std::stringstream& aDiagnostics); 
+  
+
+      
+      MAILSTREAM* getMailStream(const std::string& aHost,
+                                const std::string& aUsername,
+                                const std::string& aPassword,
+                                const std::string& aMailbox,
+                                const bool aFullOpen);
+
+
+      void status(const std::string& aHost, 
+                  const std::string& aUsername, 
+                  const std::string& aPassword, 
+                  const std::string& aMailbox);
+
+      bool create(const std::string& aHost, 
+                  const std::string& aUsername, 
+                  const std::string& aPassword, 
+                  const std::string& aMailboxName);
+
+      bool delete_mailbox(const std::string& aHost, 
+                          const std::string& aUsername, 
+                          const std::string& aPassword, 
+                          const std::string& aMailboxName);
+
+      bool rename(const std::string& aHost, 
+                  const std::string& aUserName, 
+                  const std::string& aPassword, 
+                  const std::string& aMailboxFromName, 
+                  const std::string& aMailboxToName);
+
+      bool subscription(const std::string& aHost, 
+                        const std::string& aUserName, 
+                        const std::string& aPassword, 
+                        const std::string& aMailbox, 
+                        bool subscribe);
+
+      bool expunge(const std::string& aHost, 
+                   const std::string& aUserName, 
+                   const std::string& aPassword, 
+                   const std::string& aMailbox);
+
+      bool copy(const std::string& aHost, 
+                const std::string& aUserName, 
+                const std::string& aPassword, 
+                const std::string& aMailboxFrom, 
+                const std::string& aMailboxTo, 
+                const std::string& aMessageNumbers, 
+                bool aUid, 
+                bool aCopy);
+
+
+
+      std::vector<std::string> list(const std::string& aHost, 
+                                    const std::string& aUserName, 
+                                    const std::string& aPassword, 
+                                    const std::string& aReferencePath, 
+                                    const std::string& aPattern, 
+                                    bool aOnlySuscribed);
+      
+      std::vector<long> search(const std::string& aHost, 
+                               const std::string& aUserName, 
+                               const std::string& aPassword, 
+                               const std::string& aMailbox, 
+                               const std::string& aCriteria, 
+                               bool aUid);
+     
+      ENVELOPE* fetchEnvelope(const std::string& aHost, 
+                              const std::string& aUserName, 
+                              const std::string& aPassword, 
+                              const std::string& aMailbox, 
+                              unsigned long aMessageNumber,
+                              std::vector<int>& aFlags,
+                              const bool aUid);
+
+      ENVELOPE* fetchStructure(const std::string& aHost, 
+                               const std::string& aUserName, 
+                               const std::string& aPassword, 
+                               const std::string& aMailbox, 
+                               BODY** aBody,  
+                               unsigned long aMessageNumber,
+                               bool aUid,
+                               std::vector<int>& aFlags);
+     
+      std::string fetchText(const std::string& aHost, 
+                            const std::string& aUserName,
+                            const std::string& aPassword,
+                            const std::string& aMailbox,
+                            unsigned long aMessgetNumber,
+                            bool aUid);
+
+      void fetchFlags(const std::string& aHost,
+                      const std::string& aUserName,
+                      const std::string& aPassword,
+                      const std::string& aMailbox,
+                      unsigned long aMessageNumber,
+                      std::vector<int>& aFlags,
+                      const bool aUid);
+
+
+      void setFlags(const std::string& aHost,
+                    const std::string& aUserName,
+                    const std::string& aPassword,
+                    const std::string& aMailbox,
+                    const unsigned long aMessageNumber,
+                    const std::vector<int>& aFlagsVector,
+                    const bool aUid);
+
+
+
+      std::string
+      fetchBodyFull(const std::string& aHost,
+                    const std::string& aUserName,
+                    const std::string& aPassword,
+                    const std::string& aMailbox,
+                    const unsigned long aMessageNumber,
+                    const std::string& aSection,
+                    const bool aUid); 
+
+
+       std::string
+       fetchSubject(const std::string& aHost,
+                    const std::string& aUserName,
+                    const std::string& aPassword,
+                    const std::string& aMailbox,
+                    const unsigned long aMessageNumber);
+
+       std::string
+       fetchFrom(const std::string& aHost,
+                 const std::string& aUserName,
+                 const std::string& aPassword,
+                 const std::string& aMailbox,
+                 const unsigned long aMessageNumber);
+
+
+      long
+      convertNumber(const std::string& aHost,
+                    const std::string& aUserName,
+                    const std::string& aPassword,
+                    const std::string& aMailbox,
+                    const unsigned long aMessageNumber,
+                    const bool aUid);
+
+      /*
+       * Generates a search_program out of an IMAP_rv4 complient vector of strings.
+       * The search program is then used by the mail_search_full function which hasn't got a built in parser.
+       */
+      SEARCHPGM *search_criteria(std::vector<std::string> aCriteria);
+
+      /*
+       * Returns the next string of this iterator as char *.
+       */
+      char * getNextStringAsChar(std::vector<std::string>::iterator aIterator);
+
+      /*
+       * Returns true if the passed keyword does not need an argument (according to the IMAP_rv4 search syntax.
+       */
+      bool isSingleKeyword(const std::string& aKeyword);
+  
+
+      void setUserName(const std::string& aUserName);
+      void setPassword(const std::string& aPassword);
+
+      std::string getUserName();
+      std::string getPassword();
+      std::string getError();
+      void addError(const std::string& aError);
+      
+      void addLogEntry(const std::string& aLogEntry);
+
+      void setStatus(unsigned long aMessages, unsigned long aRecent, unsigned long aUnseen, unsigned long aUIDNext, unsigned long aUIDValidity);
+  
+      void getStatus(unsigned long* aMessages, unsigned long* aRecent, unsigned long* aUnseen, unsigned long* aUIDNextm, unsigned long* aUIDValidity);  
+    
+      void addFoundSequenceNumber(long aSequenceNumber);
+      
+      
+      void addListedMailbox(const std::string& aListedMail);
+      
+
+    private:
+      //ctor, dtor, copy ctor are all hidden
+      ImapClient() {
+        theFlags.assign(6, 0);
+      };
+      ~ImapClient() {
+        // make sure that theMailstream is not open! 
+        if (theHosts.size() > 0) {
+          std::list<Host>::iterator allHostsIterator;
+          for (allHostsIterator = theHosts.begin(); allHostsIterator != theHosts.end(); allHostsIterator++) {
+            MAILSTREAM * lToClose = (*allHostsIterator).lMailStream;
+            if (lToClose) {
+              mail_close(lToClose);
+            }  
+          }
+        }
+      };
+      
+      void
+      checkMailStream(MAILSTREAM* aStream);
+
+      struct Host {
+        MAILSTREAM * lMailStream;
+        std::string lHostNameWithMailbox;
+        std::string lUsername;
+        std::string lPassword;
+        bool lIsFullOpen;
+
+      };  
+      
+      ImapClient(ImapClient const&) {};
+      std::list<Host> theHosts;
+      // the current mailstream, in future versions this could be a mailstream pool ... 
+      
+      // the Host of the current mailstream
+      
+      // string containing error message
+      std::stringstream theErrorMessage;
+      std::stringstream theLog;
+      std::string theUserName;
+      std::string thePassword;
+
+      // vars for status  
+      unsigned long theMessages;
+      unsigned long theRecent;
+      unsigned long theUnseen;
+      unsigned long theUIDNext;
+      unsigned long theUIDValidity;
+      std::vector<std::string> theListedMailboxes;
+      std::vector<long> theFoundSequenceNumbers;
+      std::vector<int> theFlags;
+    };
+
+  }//namespace email
+}//namespace zorba
+
+#endif // ZORBA_MODULES_EMAIL_UW_IMAP_H
+
+
+

=== added file 'src/com/zorba-xquery/www/modules/email/email.xsd'
--- src/com/zorba-xquery/www/modules/email/email.xsd	1970-01-01 00:00:00 +0000
+++ src/com/zorba-xquery/www/modules/email/email.xsd	2014-04-30 23:07:12 +0000
@@ -0,0 +1,174 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema";
+  targetNamespace="http://www.zorba-xquery.com/modules/email";
+  xmlns:tns="http://www.zorba-xquery.com/modules/email";
+  elementFormDefault="qualified">
+<!--
+:: Copyright 2006-2008 The FLWOR Foundation.
+::
+:: Licensed under the Apache License, Version 2.0 (the "License");
+:: you may not use this file except in compliance with the License.
+:: You may obtain a copy of the License at
+::
+:: http://www.apache.org/licenses/LICENSE-2.0
+::
+:: Unless required by applicable law or agreed to in writing, software
+:: distributed under the License is distributed on an "AS IS" BASIS,
+:: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+:: See the License for the specific language governing permissions and
+:: limitations under the License.
+::
+-->
+
+  <annotation>
+    <documentation xml:lang="en">
+      This schema defines the types used by the Zorba XQuery IMAP and SMTP modules.
+    </documentation>
+  </annotation>
+
+  <complexType name="mailboxType">
+    <sequence>
+      <element name="hostName" type="string"/>
+      <element name="mailboxName" type="string"/>
+    </sequence>
+  </complexType>
+
+  <complexType name="hostInfoType">
+    <sequence>
+      <element name="hostName" type="string"/>
+      <element name="userName" type="string"/>
+      <element name="password" type="string"/>
+    </sequence>
+  </complexType>
+
+  <complexType name="statusType">
+    <sequence>
+      <element name="messages" type="long"/>
+      <element name="recent" type="long"/>
+      <element name="unseen" type="long"/>
+      <element name="uidnext" type="long"/>
+      <element name="uidvalidity" type="long"/>
+    </sequence> 
+  </complexType>
+
+  <element name="mailbox" type="tns:mailboxType"/>
+  <element name="status" type="tns:statusType"/>
+  <element name="hostInfo" type="tns:hostInfoType"/>
+
+  <complexType name="emptyType">
+    <complexContent>
+      <restriction base="anyType"/>
+    </complexContent>
+  </complexType>
+
+  <complexType name="flagsType">
+    <all>
+     <element name="seen" type="tns:emptyType" maxOccurs="1" minOccurs="0"/>
+     <element name="deleted" type="tns:emptyType" maxOccurs="1" minOccurs="0"/>
+     <element name="flagged" type="tns:emptyType" maxOccurs="1" minOccurs="0"/>
+     <element name="answered" type="tns:emptyType" maxOccurs="1" minOccurs="0" />
+     <element name="draft" type="tns:emptyType" maxOccurs="1" minOccurs="0"/>
+    </all>
+  </complexType>
+ 
+  <element name="flags" type="tns:flagsType"/>
+
+  <simpleType name="emailAddressType">
+    <restriction base="string">
+      <pattern value="[^@]+@[^\.]+\..+"/>
+    </restriction>
+  </simpleType>
+
+  <complexType name="emailAddress">
+    <sequence>
+      <element name="name" type="string" maxOccurs="1" minOccurs="0"/>
+      <element name="email" type="tns:emailAddressType" maxOccurs="1" minOccurs="1"/>
+    </sequence>
+  </complexType>
+
+  <complexType name="recipientType">
+    <sequence>
+      <choice>
+        <element name="to" type="tns:emailAddress"/>
+        <element name="cc" type="tns:emailAddress"/>
+        <element name="bcc" type="tns:emailAddress"/>
+      </choice>
+    </sequence>
+  </complexType>
+
+  <complexType name="envelopeType">
+    <sequence>
+      <element name="remail" type="string" maxOccurs="1" minOccurs="0"/>
+      <element name="date" type="dateTime" maxOccurs="1" minOccurs="0"/>
+      <element name="from" type="tns:emailAddress" maxOccurs="1" minOccurs="0"/>
+      <element name="sender" type="tns:emailAddress" maxOccurs="1" minOccurs="0"/>
+      <element name="replyTo" type="tns:emailAddress" maxOccurs="1" minOccurs="0"/>
+      <element name="subject" type="string" maxOccurs="1" minOccurs="0"/>
+      <element name="recipient" type="tns:recipientType" maxOccurs="unbounded" minOccurs="0"/>
+      <element name="messageId" type="string" maxOccurs="1" minOccurs="0"/>
+      <element name="flags" type="tns:flagsType" maxOccurs="1" minOccurs="0"/>
+    </sequence>
+  </complexType>
+
+  <complexType name="messageType">
+    <sequence>
+      <element name="envelope" type="tns:envelopeType" maxOccurs="1" minOccurs="0"/>
+      <element name="mimeVersion" type="string" maxOccurs="1" minOccurs="0" default="1.0"/>
+      <element name="body" type="tns:bodyTypeChoice" maxOccurs="1" minOccurs="1"/>
+    </sequence>
+  </complexType>
+
+ <element name="message" type="tns:messageType"/>
+
+ <element name="envelope" type="tns:envelopeType"/>
+
+  <!-- mime definitions -->
+
+  <!-- definition of simple elements -->
+  <simpleType name="contentTypeValue">
+    <restriction base="string">
+      <pattern value="[a-zA-Z]+/[a-zA-Z0-9\-\+\.]+"/>
+    </restriction>
+  </simpleType>
+
+  <simpleType name="cteType">
+    <restriction base="string">
+      <pattern value="ENC7BIT|ENC8BIT|ENCBINARY|ENCBASE64|ENCQUOTEDPRINTABLE|ENCOTHER"/>
+    </restriction>
+  </simpleType>
+
+  <complexType name="contentType">
+    <simpleContent> 
+      <extension base="string">
+        <attribute name="contentType" type="tns:contentTypeValue"/>
+        <attribute name="charset" type="string" default="us-ascii"/>
+        <attribute name="contentTransferEncoding" type="tns:cteType" default="ENC7BIT"/>
+        <attribute name="contentDisposition" type="string"/>
+        <attribute name="contentDisposition-filename" type="string"/>
+        <attribute name="contentDisposition-modification-date" type="dateTime"/>
+        <attribute name="content-id" type="string"/>
+       </extension>
+    </simpleContent>
+  </complexType>
+
+  <complexType name="multipartType">
+    <choice maxOccurs="unbounded">
+      <element name="content" type="tns:contentType"  minOccurs="1"/>
+      <element name="multipart" type="tns:multipartType"  minOccurs="1"/>
+    </choice>
+    <attribute name="contentType" type="tns:contentTypeValue"/>
+    <attribute name="charset" type="string" default="us-ascii"/>
+    <attribute name="contentTransferEncoding" type="tns:cteType" default="ENC7BIT"/>
+    <attribute name="contentDisposition" type="string"/>
+  </complexType>
+
+  <complexType name="bodyTypeChoice">
+    <sequence>
+      <choice>
+        <element name="content" type="tns:contentType" maxOccurs="1" minOccurs="1"/>
+        <element name="multipart" type="tns:multipartType" minOccurs="1" maxOccurs="1"/>
+      </choice>
+    </sequence>
+  </complexType>
+
+ </schema>

=== added file 'src/com/zorba-xquery/www/modules/email/imap.xq'
--- src/com/zorba-xquery/www/modules/email/imap.xq	1970-01-01 00:00:00 +0000
+++ src/com/zorba-xquery/www/modules/email/imap.xq	2014-04-30 23:07:12 +0000
@@ -0,0 +1,627 @@
+xquery version "3.0";
+
+(:
+ : Copyright 2006-2009 The FLWOR Foundation.
+ :
+ : Licensed under the Apache License, Version 2.0 (the "License");
+ : you may not use this file except in compliance with the License.
+ : You may obtain a copy of the License at
+ :
+ : http://www.apache.org/licenses/LICENSE-2.0
+ :
+ : Unless required by applicable law or agreed to in writing, software
+ : distributed under the License is distributed on an "AS IS" BASIS,
+ : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ : See the License for the specific language governing permissions and
+ : limitations under the License.
+:)
+
+(:~
+ : This module provides functions for accessing and manipulating emails on mail
+ : servers through the IMAP protocol.
+ :
+ : All functions in this module receive as the first argument the IMAP host and user
+ : information. This is an element with the type <code>hostInfoType</code> as defined
+ : in the email schema: <code>http://www.zorba-xquery.com/modules/email</code>.
+ :
+ : For example:
+ : <pre class="ace-static" ace-mode="xquery"><![CDATA[
+ : <email:hostInfo>
+ :   <email:hostName>imap.example.com</email:hostName>
+ :   <email:userName>myuser</email:userName>
+ :   <email:password>mypassword</email:password>
+ : </email:hostInfo>
+ : ]]></pre>
+ :
+ : The <code>hostInfoType</code> only needs to be in the email schema namespace
+ : (<code>http://www.zorba-xquery.com/modules/email</code>). It does not need
+ : to be validated since it's validated by the module.
+ :
+ : @author Daniel Thomas, Gabriel Petrovay
+ : @see <a href="http://www.washington.edu/imap/";>c-client library part of UW IMAP toolkit</a>
+ : @library <a href="http://www.washington.edu/imap/";>c-client library part of UW IMAP toolkit</a>
+ : @project Zorba/Input Output/IMAP
+ :)
+module namespace imap = 'http://www.zorba-xquery.com/modules/email/imap';
+
+import schema namespace email = 'http://www.zorba-xquery.com/modules/email';
+
+declare namespace an = "http://zorba.io/annotations";;
+
+declare namespace ver = "http://zorba.io/options/versioning";;
+declare option ver:module-version "1.0";
+
+(:~
+ : Returns the status of the given mailbox.
+ :
+ : The status of a mailbox contains:
+ : <ul>
+ :  <li><code>messages</code>: the number of messages in the mailbox</li>
+ :  <li><code>recent</code>: the number of messages flagged as recent</li>
+ :  <li><code>unseen</code>: the number of messages flagged as unseen</li>
+ :  <li><code>uidnext</code>: the next unique identifier that will be assigned to a message</li>
+ :  <li><code>uidvalidity</code>: a value that, together with the <code>uidnext</code> value
+ :    forms a 64 bit number that must be unique for the server</li>
+ : </ul>
+ :
+ : @param $host-info The IMAP host, user name, and password.
+ : @param $mailbox The mailbox for which we want to have the status.
+ : @return The <code>status</code> of the specified <code>$mailbox</code>.
+ :    The result is validated against the schema:
+ :    <code>http://www.zorba-xquery.com/modules/email</code>.
+ : @error imap:IMAP0001 If the IMAP operation failed.
+ : @error imap:IMAP0002 If the connection to the IMAP server is refused.
+ : @error err:XQDY0027 If the value of <code>$host-info</code> is not valid
+ :    according to the email schema:
+ :    <code>http://www.zorba-xquery.com/modules/email</code>
+ : @example examples/Queries/imap/status_example.xq
+ :)
+declare %an:nondeterministic function imap:status(
+    $host-info as element(email:hostInfo),
+    $mailbox as xs:string)
+  as element(email:status)
+{
+  let $status := imap:status-impl(validate {$host-info}, $mailbox)
+  let $status-sequence := fn:tokenize($status, ',')
+  return
+    validate {
+      <email:status>
+        <email:messages>{$status-sequence[1]}</email:messages>
+        <email:recent>{$status-sequence[2]}</email:recent>
+        <email:unseen>{$status-sequence[3]}</email:unseen>
+        <email:uidnext>{$status-sequence[4]}</email:uidnext>
+        <email:uidvalidity>{$status-sequence[5]}</email:uidvalidity>
+      </email:status> 
+    }
+};
+
+declare %private %an:nondeterministic function imap:status-impl($host-info as element(email:hostInfo), $mailbox as xs:string) as xs:string* external;
+
+(:~
+ : Creates a new mailbox for the given user.
+ :
+ : @param $host-info The IMAP host, user name, and password.
+ : @param $mailbox-name The name for the new mailbox.
+ : @return The function is declared as sequential and has side-effects. It returns the empty sequence.
+ : @error imap:IMAP0001 If the IMAP operation failed.
+ : @error imap:IMAP0002 If the connection to the IMAP server is refused.
+ : @error err:XQDY0027 If the value of <code>$host-info</code> is not valid
+ :    according to the email schema:
+ :    <code>http://www.zorba-xquery.com/modules/email</code>
+ : @example examples/Queries/imap/create_rename_delete_example.xq
+ :)
+declare %an:sequential function imap:create(
+    $host-info as element(email:hostInfo),
+    $mailbox-name as xs:string)
+  as empty-sequence()
+{
+  imap:create-impl(validate {$host-info}, $mailbox-name) 
+};
+  
+declare %private %an:sequential function imap:create-impl($host-info as element(email:hostInfo), $mailbox-name as xs:string)  as empty-sequence() external; 
+
+(:~
+ : Deletes a mailbox for the given user.
+ :
+ : @param $host-info The IMAP host, user name, and password.
+ : @param $mailbox-name The name of the mailbox to delete.
+ : @return The function is declared as sequential and has side-effects. It returns the empty sequence.
+ : @error imap:IMAP0001 If the IMAP operation failed.
+ : @error imap:IMAP0002 If the connection to the IMAP server is refused.
+ : @error err:XQDY0027 If the value of <code>$host-info</code> is not valid
+ :    according to the email schema:
+ :    <code>http://www.zorba-xquery.com/modules/email</code>
+ : @example examples/Queries/imap/create_rename_delete_example.xq
+ :)
+declare %an:sequential function imap:delete(
+    $host-info as element(email:hostInfo),
+    $mailbox-name as xs:string)
+  as empty-sequence()
+{
+  imap:delete-impl(validate {$host-info}, $mailbox-name)
+};
+
+declare %private %an:sequential function imap:delete-impl($host-info as element(email:hostInfo), $mailbox-name as xs:string)  as empty-sequence() external; 
+
+(:~
+ : Renames a mailbox.
+ :
+ : @param $host-info The IMAP host, user name, and password.
+ : @param $mailbox-old The name of the mailbox we want to rename.
+ : @param $mailbox-new The new name for the mailbox.
+ : @return The function is declared as sequential and has side-effects. It returns the empty sequence.
+ : @error imap:IMAP0001 If the IMAP operation failed.
+ : @error imap:IMAP0002 If the connection to the IMAP server is refused.
+ : @error err:XQDY0027 If the value of <code>$host-info</code> is not valid
+ :    according to the email schema:
+ :    <code>http://www.zorba-xquery.com/modules/email</code>
+ : @example examples/Queries/imap/create_rename_delete_example.xq
+ :)
+declare %an:sequential function imap:rename(
+    $host-info as element(email:hostInfo),
+    $mailbox-old as xs:string,
+    $mailbox-new as xs:string)
+  as empty-sequence()
+{
+  imap:rename-impl(validate {$host-info}, $mailbox-old, $mailbox-new) 
+};
+
+declare %private %an:sequential function imap:rename-impl($host-info as element(email:hostInfo), $mailbox-old as xs:string, $mailbox-new as xs:string) as empty-sequence() external;
+
+(:~
+ : Lists IMAP folders for the specified user on the host that match the pattern. 
+ :
+ : @param $host-info The IMAP host, user name, and password.
+ : @param $mailbox-ref is applied to pattern in an implementation dependent fashion to search for matching mailbox names. 
+ : @param $pattern The pattern for mailboxes to look for (can include wildcards '*' and '%').
+ : @param $only-subscribed If set true, only mailboxes are listed to which the user is subscribed.
+ : @return A sequence of <code>mailbox</code> elements.
+ :    The result elements are validated against the schema:
+ :    <code>http://www.zorba-xquery.com/modules/email</code>.
+ : @error imap:IMAP0001 If the IMAP operation failed.
+ : @error imap:IMAP0002 If the connection to the IMAP server is refused.
+ : @error err:XQDY0027 If the value of <code>$host-info</code> is not valid
+ :    according to the email schema:
+ :    <code>http://www.zorba-xquery.com/modules/email</code>
+ : @example examples/Queries/imap/list_example.xq
+ :)
+declare %an:nondeterministic function imap:list(
+    $host-info as element(email:hostInfo),
+    $mailbox-ref as xs:string,
+    $pattern as xs:string,
+    $only-subscribed as xs:boolean)
+  as element(email:mailbox)*
+{
+  let $mailbox-sequence := imap:list-impl(validate {$host-info}, $mailbox-ref, $pattern, $only-subscribed)
+  for $mailbox in $mailbox-sequence
+  return
+  validate {
+    <email:mailbox>
+      <email:hostName>{$host-info/email:hostName/text()}</email:hostName>
+      <email:mailboxName>{fn:substring-after($mailbox, '}')}</email:mailboxName>
+    </email:mailbox>
+  }
+};
+
+declare %private %an:nondeterministic function imap:list-impl($host-info as element(email:hostInfo), $mailbox-ref as xs:string, $pattern as xs:string, $only-subscribed as xs:boolean) as xs:string* external;
+
+(:~
+ : Subscribes the user to the specified mailbox.
+ : 
+ : @param $host-info The IMAP host, user name, and password.
+ : @param $mailbox The mailbox the user wants to subscribe to.
+ : @return The function is declared as sequential and has side-effects. It returns the empty sequence.
+ : @error imap:IMAP0001 If the IMAP operation failed.
+ : @error imap:IMAP0002 If the connection to the IMAP server is refused.
+ : @error err:XQDY0027 If the value of <code>$host-info</code> is not valid
+ :    according to the email schema:
+ :    <code>http://www.zorba-xquery.com/modules/email</code>
+ : @example examples/Queries/imap/subscribe_unsubscribe_example.xq
+ :)
+declare %an:sequential function imap:subscribe(
+    $host-info as element(email:hostInfo),
+    $mailbox as xs:string)
+  as empty-sequence() 
+{
+  imap:subscribe-impl(validate {$host-info}, $mailbox)
+};
+
+declare %private %an:sequential function imap:subscribe-impl($host-info as element(email:hostInfo), $mailbox as xs:string) as empty-sequence() external;
+
+(:~
+ : Unsubscribes the user from the specified mailbox.
+ : 
+ : @param $host-info The IMAP host, user name, and password.
+ : @param $mailbox The mailbox the user wants to unsubscribe from.
+ : @return The function is declared as sequential and has side-effects. It returns the empty sequence.
+ : @error imap:IMAP0001 If the IMAP operation failed.
+ : @error imap:IMAP0002 If the connection to the IMAP server is refused.
+ : @error err:XQDY0027 If the value of <code>$host-info</code> is not valid
+ :    according to the email schema:
+ :    <code>http://www.zorba-xquery.com/modules/email</code>
+ : @example examples/Queries/imap/subscribe_unsubscribe_example.xq
+ :)
+declare %an:sequential function imap:unsubscribe(
+    $host-info as element(email:hostInfo),
+    $mailbox as xs:string)
+  as empty-sequence()
+{
+  imap:unsubscribe-impl(validate {$host-info}, $mailbox)
+};
+
+declare %private %an:sequential function imap:unsubscribe-impl($host-info as element(email:hostInfo), $mailbox as xs:string) as empty-sequence() external;
+
+(:~
+ : Permanently deletes all messages of the given mailbox that have the "deleted" flag set.
+ : 
+ : @param $host-info The IMAP host, user name, and password.
+ : @param $mailbox The mailbox for which all messages that have the \Deleted flag set should be permanently deleted.
+ : @return The function is declared as sequential and has side-effects. It returns the empty sequence.
+ : @error imap:IMAP0001 If the IMAP operation failed.
+ : @error imap:IMAP0002 If the connection to the IMAP server is refused.
+ : @error err:XQDY0027 If the value of <code>$host-info</code> is not valid
+ :    according to the email schema:
+ :    <code>http://www.zorba-xquery.com/modules/email</code>
+ : @example examples/Queries/imap/expunge_example.xq
+ :) 
+declare %an:sequential function imap:expunge(
+    $host-info as element(email:hostInfo),
+    $mailbox as xs:string)
+  as empty-sequence()
+{
+  imap:expunge-impl(validate {$host-info}, $mailbox)
+};
+
+declare %private %an:sequential function imap:expunge-impl($host-info as element(email:hostInfo), $mailbox as xs:string) as empty-sequence() external;
+
+(:~
+ : Searches a mailbox for messages that match the given criteria.
+ : The criteria should be a string as defined in the RFC3501 (IMAP4rev1).
+ : A valid example would be: 'FROM zorba@xxxxxxxxx OR NOT SUBJECT Bug'. 
+ : Depending on the value of <code>$uid</code>, the function will either
+ : return matching sequence numbers or unique identifiers.
+ :
+ : @param $host-info The IMAP host, user name, and password.
+ : @param $mailbox The mailbox to search.
+ : @param $criteria The searching criteria.
+ : @param $uid If true, the function returns the sequence of unique identifiers
+ :    corresponding to the matching mails, else the corresponding sequence
+ :    numbers are returned. 
+ : @return Either the sequence of matching sequence numbers or the sequence of
+ :    matching unique identifiers.
+ : @error imap:IMAP0001 If the IMAP operation failed.
+ : @error imap:IMAP0002 If the connection to the IMAP server is refused.
+ : @error err:XQDY0027 If the value of <code>$host-info</code> is not valid
+ :    according to the email schema:
+ :    <code>http://www.zorba-xquery.com/modules/email</code>
+ : @example examples/Queries/imap/search_example.xq
+ :)
+declare %an:nondeterministic function imap:search(
+    $host-info as element(email:hostInfo),
+    $mailbox as xs:string,
+    $criteria as xs:string,
+    $uid as xs:boolean?)
+  as xs:long*
+{
+  imap:search-impl(validate {$host-info}, $mailbox, $criteria, $uid)
+}; 
+
+declare %private %an:nondeterministic function imap:search-impl($host-info as element(email:hostInfo), $mailbox as xs:string, $criteria as xs:string, $uid as xs:boolean?) as xs:long* external;
+
+(:~
+ : Copies messages between mailboxes.
+ :
+ : Depending on the value of <code>$uid</code>, the messages are either specified
+ : through their sequence number or through their unique id. Both mailboxes must exist.
+ : 
+ : @param $host-info The IMAP host, user name, and password.
+ : @param $mailbox-from The mailbox in which the messages reside.
+ : @param $mailbox-to The mailbox in to which the messages are copied.
+ : @param $messages The messages to be copied, specified either by their sequence number or their unique id.
+ : @param $uid If true, <code>$messages</code> are treated as sequence numbers. Else as unique identifiers.
+ : @return The function is declared as sequential and has side-effects. It returns the empty sequence.
+ : @error imap:IMAP0001 If the IMAP operation failed.
+ : @error imap:IMAP0002 If the connection to the IMAP server is refused.
+ : @error imap:IMAP0003 If no message is found with the provided sequence number/unique identifier.
+ : @error err:XQDY0027 If the value of <code>$host-info</code> is not valid
+ :    according to the email schema:
+ :    <code>http://www.zorba-xquery.com/modules/email</code>
+ : @example examples/Queries/imap/copy_example.xq
+ :)
+declare %an:sequential function imap:copy(
+    $host-info as element(email:hostInfo),
+    $mailbox-from as xs:string,
+    $mailbox-to as xs:string,
+    $messages as xs:long+,
+    $uid as xs:boolean?)
+  as empty-sequence()
+{
+  imap:copy-impl(validate {$host-info}, $mailbox-from, $mailbox-to, $messages, $uid, true());
+};
+
+declare %private %an:sequential function imap:copy-impl($host-info as element(email:hostInfo), $mailbox-from as xs:string, $mailbox-to as xs:string, $messages as xs:long+, $uid as xs:boolean?, $copy as xs:boolean) as empty-sequence() external;
+
+(:~
+ : Moves messages between mailboxes.
+ :
+ : Depending on the value of <code>$uid</code>, the messages are either specified through
+ : their sequence number or through their unique id. Both mailboxes must exist.
+ : 
+ : @param $host-info The IMAP host, user name, and password.
+ : @param $mailbox-from The mailbox in which the messages reside.
+ : @param $mailbox-to The mailbox in to which the messages should be moved.
+ : @param $messages The messages to be copied, specified either by their sequence number or their unique id.
+ : @param $uid If true, <code>$messages</code> are treated as sequence numbers. Else as unique identifiers.
+ : @return The function is declared as sequential and has side-effects. It returns the empty sequence.
+ : @error imap:IMAP0001 If the IMAP operation failed.
+ : @error imap:IMAP0002 If the connection to the IMAP server is refused.
+ : @error imap:IMAP0003 If no message is found with the provided sequence number/unique identifier.
+ : @error err:XQDY0027 If the value of <code>$host-info</code> is not valid
+ :    according to the email schema:
+ :    <code>http://www.zorba-xquery.com/modules/email</code>
+ : @example examples/Queries/imap/move_example.xq
+ :)
+declare %an:sequential function imap:move(
+    $host-info as element(email:hostInfo),
+    $mailbox-from as xs:string,
+    $mailbox-to as xs:string,
+    $messages as xs:long+,
+    $uid as xs:boolean?)
+  as empty-sequence()
+{
+  imap:copy-impl(validate {$host-info}, $mailbox-from, $mailbox-to, $messages, $uid, false());
+};
+
+(:~
+ : Fetches the envelope of a message. 
+ :
+ : @param $host-info The IMAP host, user name, and password.
+ : @param $mailbox The mailbox in which to search for the message.
+ : @param $message-number The message for which to fetch the envelope (depending on
+ :    <code>$uid</code> either as message sequence number or unique identifier).
+ : @param $uid If true, <code>$message-number</code> is treated as sequence number. Else as unique identifier.
+ : @return The <code>envelope</code> of the requested message.
+ :    The result is validated against the schema:
+ :    <code>http://www.zorba-xquery.com/modules/email</code>.
+ : @error imap:IMAP0001 If the IMAP operation failed.
+ : @error imap:IMAP0002 If the connection to the IMAP server is refused.
+ : @error imap:IMAP0003 If no message is found with the provided sequence number/unique identifier.
+ : @error err:XQDY0027 If the value of <code>$host-info</code> is not valid
+ :    according to the email schema:
+ :    <code>http://www.zorba-xquery.com/modules/email</code>
+ : @example examples/Queries/imap/fetch_envelope_example.xq 
+ :) 
+declare %an:nondeterministic function imap:fetch-envelope(
+    $host-info as element(email:hostInfo),
+    $mailbox as xs:string,
+    $message-number as xs:long,
+    $uid as xs:boolean?)
+  as element(email:envelope)
+{
+  validate {imap:fetch-envelope-impl( validate { $host-info }, $mailbox , $message-number, $uid )} 
+};
+
+declare %private %an:nondeterministic function imap:fetch-envelope-impl($host-info as element(email:hostInfo), $mailbox as xs:string, $message-number as xs:long, $uid as xs:boolean?) as element(email:envelope) external;
+
+(:~
+ : Fetches a whole message.
+ : 
+ : @param $host-info The IMAP host, user name, and password.
+ : @param $mailbox The mailbox in which to search for the message.
+ : @param $message-number The message to fetch, denoted either by its sequence number or unique identifier.
+ : @param $uid If true, <code>$message-number</code> is treated as sequence number. Else as unique identifier.
+ : @return the <code>message</code> with the given <code>$message-number</code>.
+ :    The result is validated against the schema:
+ :    <code>http://www.zorba-xquery.com/modules/email</code>.
+ : @error imap:IMAP0001 If the IMAP operation failed.
+ : @error imap:IMAP0002 If the connection to the IMAP server is refused.
+ : @error imap:IMAP0003 If no message is found with the provided sequence number/unique identifier.
+ : @error err:XQDY0027 If the value of <code>$host-info</code> is not valid
+ :    according to the email schema:
+ :    <code>http://www.zorba-xquery.com/modules/email</code>
+ : @example examples/Queries/imap/fetch_message_example.xq
+ :)
+declare %an:nondeterministic function imap:fetch-message(
+    $host-info as element(email:hostInfo),
+    $mailbox as xs:string,
+    $message-number as xs:long,
+    $uid as xs:boolean)
+  as element(email:message)
+{
+  validate {imap:fetch-message-impl(validate {$host-info}, $mailbox, $message-number, $uid)} 
+}; 
+
+declare %private %an:nondeterministic function imap:fetch-message-impl($host-info as element(email:hostInfo), $mailbox as xs:string, $message-number as xs:long, $uid as xs:boolean) as element() external;
+
+(:~
+ : Fetches the subject for a message.
+ :
+ : Please note that this function only works with message sequence numbers,
+ : not with unique identifiers. Only the first 255 characters of a subject
+ : are fetched.
+ :
+ : @param $host-info The IMAP host, user name, and password.
+ : @param $mailbox The mailbox for which we want to get the subject of a message.
+ : @param $message-number Denotes the message for which we want the subject.
+ : @return The subject of the specified message.
+ : @error imap:IMAP0001 If the IMAP operation failed.
+ : @error imap:IMAP0002 If the connection to the IMAP server is refused.
+ : @error imap:IMAP0003 If no message is found with the provided sequence number/unique identifier.
+ : @error err:XQDY0027 If the value of <code>$host-info</code> is not valid
+ :    according to the email schema:
+ :    <code>http://www.zorba-xquery.com/modules/email</code>
+ : @example examples/Queries/imap/fetch_subject_example.xq
+ :)
+declare %an:nondeterministic function imap:fetch-subject(
+    $host-info as element(email:hostInfo),
+    $mailbox as xs:string,
+    $message-number as xs:long)
+  as xs:string
+{
+  imap:fetch-subject-impl(validate {$host-info}, $mailbox, $message-number)
+};
+
+declare %private %an:nondeterministic function imap:fetch-subject-impl($host-info as element(email:hostInfo), $mailbox as xs:string, $message-number as xs:long) as xs:string external;
+
+(:~
+ : Fetches the 'from' string of a message.
+ :
+ : Please note that this function only words with message sequence numbers,
+ : not with unique identifiers. Only the first 255 characters of a 'from'
+ : string are fetched.
+ : 
+ : @param $host-info The IMAP host, user name, and password.
+ : @param $mailbox The mailbox for which we want to get the 'from' string of a message.
+ : @param $message-number Denotes the message for which we want the 'from' string.
+ : @return The 'from' string of the specified message.
+ : @error imap:IMAP0001 If the IMAP operation failed.
+ : @error imap:IMAP0002 If the connection to the IMAP server is refused.
+ : @error imap:IMAP0003 If no message is found with the provided sequence number/unique identifier.
+ : @error err:XQDY0027 If the value of <code>$host-info</code> is not valid
+ :    according to the email schema:
+ :    <code>http://www.zorba-xquery.com/modules/email</code>
+ : @example examples/Queries/imap/fetch_from_example.xq
+ :)
+declare %an:nondeterministic function imap:fetch-from(
+    $host-info as element(email:hostInfo),
+    $mailbox as xs:string,
+    $message-number as xs:long)
+  as xs:string
+{
+  imap:fetch-from-impl(validate {$host-info}, $mailbox, $message-number)
+};
+
+declare %private %an:nondeterministic function imap:fetch-from-impl($host-info as element(email:hostInfo), $mailbox as xs:string, $message-number as xs:long) as xs:string external;
+
+(:~
+ : Fetches the unique identifier for a given message sequence number.
+ :
+ : @param $host-info The IMAP host, user name, and password.
+ : @param $mailbox The mailbox for which we want to get the unique identifier of a message sequence number.
+ : @param $message-number The message sequence number for which we want the unique identifier. 
+ : @return The unique identifier of the given message sequence number.
+ : @error imap:IMAP0001 If the IMAP operation failed.
+ : @error imap:IMAP0002 If the connection to the IMAP server is refused.
+ : @error imap:IMAP0003 If no message is found with the provided sequence number/unique identifier.
+ : @error err:XQDY0027 If the value of <code>$host-info</code> is not valid
+ :    according to the email schema:
+ :    <code>http://www.zorba-xquery.com/modules/email</code>
+ : @example examples/Queries/imap/fetch_uid_example.xq
+ :)
+declare %an:nondeterministic function imap:fetch-uid(
+    $host-info as element(email:hostInfo),
+    $mailbox as xs:string,
+    $message-number as xs:long)
+  as xs:long
+{
+  imap:fetch-uid-impl(validate {$host-info}, $mailbox, $message-number)
+};
+
+declare %private %an:nondeterministic function imap:fetch-uid-impl($host-info as element(email:hostInfo), $mailbox as xs:string, $message-number as xs:long) as xs:long external;
+
+(:~
+ : Fetches the message sequence number for a given unique identifier.
+ :
+ : @param $host-info The IMAP host, user name, and password.
+ : @param $mailbox The mailbox for which we want to get the message sequence number of an unique identifier.
+ : @param $message-number The unique identifier for which we want the message sequence number.
+ : @return The message sequence number of the of the given unique identifier.
+ : @error imap:IMAP0001 If the IMAP operation failed.
+ : @error imap:IMAP0002 If the connection to the IMAP server is refused.
+ : @error imap:IMAP0003 If no message is found with the provided sequence number/unique identifier.
+ : @error err:XQDY0027 If the value of <code>$host-info</code> is not valid
+ :    according to the email schema:
+ :    <code>http://www.zorba-xquery.com/modules/email</code>
+ : @example examples/Queries/imap/fetch_message_sequence_number_example.xq
+ :)
+declare %an:nondeterministic function imap:fetch-message-sequence-number(
+    $host-info as element(email:hostInfo),
+    $mailbox as xs:string,
+    $message-number as xs:long)
+  as xs:long
+{
+  imap:fetch-message-sequence-number-impl(validate {$host-info}, $mailbox, $message-number)
+};
+
+declare %private %an:nondeterministic function imap:fetch-message-sequence-number-impl($host-info as element(email:hostInfo), $mailbox as xs:string, $message-number as xs:long) as xs:long external;
+
+(:~
+ : Fetches the flags of a message.
+ :
+ : @param $host-info The IMAP host, user name, and password.
+ : @param $mailbox The mailbox containing the specified message.
+ : @param $message-number Either the message sequence number or the unique identifier of the message.
+ : @param $uid If true, <code>$message-number</code> is treated as sequence number. Else as unique identifier.
+ : @return The <code>flags</code> of the specified message.
+ :    The result is validated against the schema:
+ :    <code>http://www.zorba-xquery.com/modules/email</code>.
+ : @error imap:IMAP0001 If the IMAP operation failed.
+ : @error imap:IMAP0002 If the connection to the IMAP server is refused.
+ : @error imap:IMAP0003 If no message is found with the provided sequence number/unique identifier.
+ : @error err:XQDY0027 If the value of <code>$host-info</code> is not valid
+ :    according to the email schema:
+ :    <code>http://www.zorba-xquery.com/modules/email</code>
+ : @example examples/Queries/imap/fetch_flags_example.xq
+ :)
+declare %an:nondeterministic function imap:fetch-flags(
+    $host-info as element(email:hostInfo),
+    $mailbox as xs:string,
+    $message-number as xs:long,
+    $uid as xs:boolean?)
+  as element(email:flags) 
+{
+  validate {imap:fetch-flags-impl(validate{$host-info}, $mailbox, $message-number, $uid)} 
+};
+
+declare %private %an:nondeterministic function imap:fetch-flags-impl($host-info as element(email:hostInfo), $mailbox as xs:string, $message-number as xs:long, $uid as xs:boolean?) as element(email:flags) external;
+
+(:~
+ : Sets the flags for a given message.
+ :
+ : The flags are set and unset according to the passed <code>$flags</code>.
+ :
+ : @param $host-info The IMAP host, user name, and password.
+ : @param $mailbox The mailbox containing the specified message.
+ : @param $message-number Either the message sequence number or the unique
+ :    identifier of the message (depending on the value of <code>$uid</code>).
+ : @param $flags Defines which flags should be set for this message.
+ :    The possibilities are "seen", "deleted", "flagged", "answered", and "draft".
+ :    Setting all flags at once is done by passing the element:
+ :    <code>
+ :    &lt;email:flags&gt;
+ :      &lt;email:seen/&gt;
+ :      &lt;email:deleted/&gt;
+ :      &lt;email:flagged/&gt;
+ :      &lt;email:answered/&gt;
+ :      &lt;email:draft/&gt;
+ :    &lt;/email:flags&gt;
+ :    </code>.
+ :
+ :    Setting "flagged" only and unsetting all other at once can be done by passing:
+ :    <code>
+ :    &lt;email:flags&gt;
+ :      &lt;email:flagged/&gt;
+ :    &lt;/email:flags&gt;
+ :    </code>. 
+ : @param $uid If true, <code>$message-number</code> is treated as sequence number. Else as unique identifier.
+ : @return The function is declared as sequential and has side-effects. It returns the empty sequence.
+ : @error imap:IMAP0001 If the IMAP operation failed.
+ : @error imap:IMAP0002 If the connection to the IMAP server is refused.
+ : @error imap:IMAP0003 If no message is found with the provided sequence number/unique identifier.
+ : @error err:XQDY0027 If the value of <code>$host-info</code> is not valid
+ :    according to the email schema:
+ :    <code>http://www.zorba-xquery.com/modules/email</code>
+ : @example examples/Queries/imap/set_flags_example.xq
+ :)
+declare %an:sequential function imap:set-flags(
+    $host-info as element(email:hostInfo),
+    $mailbox as xs:string,
+    $message-number as xs:long,
+    $flags as element(email:flags),
+    $uid as xs:boolean?)
+  as empty-sequence()
+{
+  imap:set-flags-impl(validate{$host-info}, $mailbox, $message-number, validate{$flags}, $uid)
+}; 
+
+declare %private %an:sequential function imap:set-flags-impl($host-info as element(email:hostInfo), $mailbox as xs:string, $message-number as xs:long, $flags as element(email:flags), $uid as xs:boolean?) as empty-sequence() external;

=== added directory 'src/com/zorba-xquery/www/modules/email/imap.xq.src'
=== added file 'src/com/zorba-xquery/www/modules/email/imap.xq.src/imap.cpp'
--- src/com/zorba-xquery/www/modules/email/imap.xq.src/imap.cpp	1970-01-01 00:00:00 +0000
+++ src/com/zorba-xquery/www/modules/email/imap.xq.src/imap.cpp	2014-04-30 23:07:12 +0000
@@ -0,0 +1,866 @@
+/*
+ * Copyright 2006-2008 The FLWOR Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "imap.h"
+
+#include <iostream>
+#include <sstream>
+#include <algorithm>
+#include <string>
+
+#include <zorba/singleton_item_sequence.h>
+#include <zorba/vector_item_sequence.h>
+#include <zorba/empty_sequence.h>
+#include <zorba/user_exception.h>
+#include <zorba/xquery_functions.h>
+
+#include "imap_module.h"
+#include "imap_client.h"
+#include "email_exception.h"
+
+
+namespace zorba { namespace emailmodule {
+
+  
+//*****************************************************************************
+
+StatusFunction::StatusFunction(const ImapModule* aModule)
+  : ImapFunction(aModule)
+{
+}
+  
+ItemSequence_t
+StatusFunction::evaluate(
+  const ExternalFunction::Arguments_t& aArgs,
+  const StaticContext*                          aSctxCtx,
+  const DynamicContext*                         aDynCtx) const
+{
+  try {
+    std::string lHostName;
+    std::string lUserName;
+    std::string lPassword;
+    getHostUserPassword(aArgs, 0, lHostName, lUserName, lPassword);
+    String lMailbox = getOneStringArg(aArgs, 1);
+    ImapClient::Instance().status(lHostName, lUserName, lPassword, lMailbox.c_str());
+    std::string lErrorMessage = ImapClient::Instance().getError();
+    if (lErrorMessage.size() != 0) {
+      raiseImapError("IMAP0001", lErrorMessage);
+    }  
+    
+    unsigned long lMessages;
+    unsigned long lRecent;
+    unsigned long lUnseen;
+    unsigned long lUIDNext;
+    unsigned long lUIDValidity;
+    
+    ImapClient::Instance().getStatus(&lMessages, &lRecent, &lUnseen, &lUIDNext, &lUIDValidity);
+    
+    std::stringstream lResult;
+    lResult << lMessages << "," << lRecent << "," << lUnseen << "," << lUIDNext << "," << lUIDValidity;
+    
+    std::string lResultString = lResult.str(); 
+    return ItemSequence_t(new SingletonItemSequence(
+      theModule->getItemFactory()->createString(lResultString.c_str())));
+  } catch (EmailException& e) {
+    raiseImapError(e);
+  }
+  return ItemSequence_t(NULL);
+}
+
+//*****************************************************************************
+
+CreateFunction::CreateFunction(const ImapModule* aModule)
+  : ImapFunction(aModule)
+{
+}
+
+ItemSequence_t
+CreateFunction::evaluate(
+  const ExternalFunction::Arguments_t& aArgs,
+  const StaticContext*                          aSctxCtx,
+  const DynamicContext*                         aDynCtx) const
+{
+  try {
+    std::string lHostName;
+    std::string lUserName;
+    std::string lPassword;
+    getHostUserPassword(aArgs, 0, lHostName, lUserName, lPassword);
+    String lMailboxName = getOneStringArg(aArgs, 1);
+    bool lSuccess = ImapClient::Instance().create(lHostName, lUserName, lPassword, lMailboxName.c_str());
+    if (!lSuccess) {
+      std::string lErrorMessage = ImapClient::Instance().getError();
+      raiseImapError("IMAP0001", lErrorMessage);
+    }
+    
+  } catch (EmailException& e) {
+    raiseImapError(e);
+  }
+  return ItemSequence_t(NULL);
+}
+
+//*****************************************************************************
+
+DeleteFunction::DeleteFunction(const ImapModule* aModule)
+  : ImapFunction(aModule)
+{
+}
+
+ItemSequence_t
+DeleteFunction::evaluate(
+  const ExternalFunction::Arguments_t& aArgs,
+  const StaticContext*                          aSctxCtx,
+  const DynamicContext*                         aDynCtx) const
+{
+  try {
+    std::string lHostName;
+    std::string lUserName;
+    std::string lPassword;
+    getHostUserPassword(aArgs, 0, lHostName, lUserName, lPassword);
+    String lMailboxName = getOneStringArg(aArgs, 1);
+    bool lSuccess = ImapClient::Instance().delete_mailbox(lHostName, lUserName, lPassword, lMailboxName.c_str());
+    
+    if (!lSuccess) {
+      std::string lErrorMessage = ImapClient::Instance().getError();
+      raiseImapError("IMAP0001", lErrorMessage);
+    }
+    
+  } catch (EmailException& e) {
+    raiseImapError(e);
+  }
+  return ItemSequence_t(NULL);
+}
+
+//*****************************************************************************
+
+RenameFunction::RenameFunction(const ImapModule* aModule)
+  : ImapFunction(aModule)
+{
+}
+
+ItemSequence_t
+RenameFunction::evaluate(
+  const ExternalFunction::Arguments_t& aArgs,
+  const StaticContext*                          aSctxCtx,
+  const DynamicContext*                         aDynCtx) const
+{
+  try {
+    std::string lHostName;
+    std::string lUserName;
+    std::string lPassword;
+    getHostUserPassword(aArgs, 0, lHostName, lUserName, lPassword);
+    String lMailboxFromName = getOneStringArg(aArgs, 1);
+    String lMailboxToName = getOneStringArg(aArgs, 2);
+    bool lSuccess = ImapClient::Instance().rename(lHostName, lUserName, lPassword, lMailboxFromName.c_str(), lMailboxToName.c_str());
+    if (!lSuccess) {
+      std::string lErrorMessage = ImapClient::Instance().getError();
+      raiseImapError("IMAP0001", lErrorMessage);
+    }
+    
+  } catch (EmailException& e) {
+    raiseImapError(e);
+  }
+  return ItemSequence_t(NULL);
+}
+
+//*****************************************************************************
+
+ListFunction::ListFunction(const ImapModule* aModule)
+  : ImapFunction(aModule)
+{
+}
+
+ItemSequence_t
+ListFunction::evaluate(
+  const ExternalFunction::Arguments_t& aArgs,
+  const StaticContext*                          aSctxCtx,
+  const DynamicContext*                         aDynCtx) const
+{
+  try {
+    std::string lHostName;
+    std::string lUserName;
+    std::string lPassword;
+    getHostUserPassword(aArgs, 0, lHostName, lUserName, lPassword);
+    String lReferencePath = getOneStringArg(aArgs, 1);
+    String lPattern = getOneStringArg(aArgs, 2);
+    bool lOnlySuscribed = getOneBoolArg(aArgs, 3);
+    
+    std::vector<std::string> lListedMailboxes = ImapClient::Instance().list(lHostName, lUserName, lPassword, lReferencePath.c_str(), lPattern.c_str(), lOnlySuscribed);
+    std::string lErrorMessage = ImapClient::Instance().getError();
+    if (lErrorMessage.size() != 0) {
+      raiseImapError("IMAP0001", lErrorMessage);
+    }
+    // explicitly return an empty sequence if there are no elements to return
+    if (lListedMailboxes.size() == 0) {
+      return ItemSequence_t(new EmptySequence());
+    }   
+    
+    int lVectorSize = (int)lListedMailboxes.size();
+    std::vector<Item> lItemVector;
+    for (int i = 0; i < lVectorSize; i++) {
+      lItemVector.push_back(theModule->getItemFactory()->createString(lListedMailboxes[i]));
+    }  
+    
+    return ItemSequence_t(new VectorItemSequence(lItemVector));
+  } catch (EmailException& e) {
+    raiseImapError(e);
+  }
+  return ItemSequence_t(NULL);
+}
+
+//*****************************************************************************
+
+SubscribeFunction::SubscribeFunction(const ImapModule* aModule)
+  : ImapFunction(aModule)
+{
+}
+
+ItemSequence_t
+SubscribeFunction::evaluate(
+  const ExternalFunction::Arguments_t& aArgs,
+  const StaticContext*                          aSctxCtx,
+  const DynamicContext*                         aDynCtx) const
+{
+  try {
+    std::string lHostName;
+    std::string lUserName;
+    std::string lPassword;
+    getHostUserPassword(aArgs, 0, lHostName, lUserName, lPassword);
+    String lMailbox = getOneStringArg(aArgs, 1);
+    
+    bool lSuccess = ImapClient::Instance().subscription(lHostName, lUserName, lPassword, lMailbox.c_str(), true);
+    if (!lSuccess) {
+      std::string lErrorMessage = ImapClient::Instance().getError();
+      raiseImapError("IMAP0001", lErrorMessage);
+    }
+    
+  } catch (EmailException& e) {
+    raiseImapError(e);
+  }
+  return ItemSequence_t(NULL);
+}
+
+//*****************************************************************************
+
+UnsubscribeFunction::UnsubscribeFunction(const ImapModule* aModule)
+  : ImapFunction(aModule)
+{
+}
+
+ItemSequence_t
+UnsubscribeFunction::evaluate(
+  const ExternalFunction::Arguments_t& aArgs,
+  const StaticContext*                          aSctxCtx,
+  const DynamicContext*                         aDynCtx) const
+{
+  try {
+    std::string lHostName;
+    std::string lUserName;
+    std::string lPassword;
+    getHostUserPassword(aArgs, 0, lHostName, lUserName, lPassword);
+    String lMailbox = getOneStringArg(aArgs, 1);
+    
+    bool lSuccess = ImapClient::Instance().subscription(lHostName, lUserName, lPassword, lMailbox.c_str(), false);
+    if (!lSuccess) {
+      std::string lErrorMessage = ImapClient::Instance().getError();
+      raiseImapError("IMAP0001", lErrorMessage);
+    }
+    
+  } catch (EmailException& e) {
+    raiseImapError(e);
+  }
+  return ItemSequence_t(NULL);
+}
+
+//*****************************************************************************
+
+ExpungeFunction::ExpungeFunction(const ImapModule* aModule)
+  : ImapFunction(aModule)
+{
+}
+
+ItemSequence_t
+ExpungeFunction::evaluate(
+  const ExternalFunction::Arguments_t& aArgs,
+  const StaticContext*                          aSctxCtx,
+  const DynamicContext*                         aDynCtx) const
+{
+  try {
+    std::string lHostName;
+    std::string lUserName;
+    std::string lPassword;
+    getHostUserPassword(aArgs, 0, lHostName, lUserName, lPassword);
+    String lMailbox = getOneStringArg(aArgs, 1);
+    
+    bool lSuccess = ImapClient::Instance().expunge(lHostName, lUserName, lPassword, lMailbox.c_str());
+    if (!lSuccess) {
+      std::string lErrorMessage = ImapClient::Instance().getError();
+      raiseImapError("IMAP0001", lErrorMessage);
+    }
+    
+  } catch (EmailException& e) {
+    raiseImapError(e);
+  }
+  return ItemSequence_t(NULL);
+}
+
+//*****************************************************************************
+
+SearchFunction::SearchFunction(const ImapModule* aModule)
+  : ImapFunction(aModule)
+{
+}
+
+ItemSequence_t
+SearchFunction::evaluate(
+  const ExternalFunction::Arguments_t& aArgs,
+  const StaticContext*                          aSctxCtx,
+  const DynamicContext*                         aDynCtx) const
+{
+  try {
+    std::string lHostName;
+    std::string lUserName;
+    std::string lPassword;
+    getHostUserPassword(aArgs, 0, lHostName, lUserName, lPassword);
+    String lMailbox = getOneStringArg(aArgs, 1);
+    String lCriteria = getOneStringArg(aArgs, 2);
+    // get none or one boolean arg
+    bool lUid = false;
+    Item lItem;
+    Iterator_t arg3_iter = aArgs[3]->getIterator();
+    arg3_iter->open();
+    if (arg3_iter->next(lItem)) {
+      lUid = lItem.getBooleanValue();
+    }  
+    arg3_iter->close();
+    std::vector<long> lFoundSequenceNumbers = ImapClient::Instance().search(lHostName, lUserName, lPassword, lMailbox.c_str(), lCriteria.c_str(), lUid);
+    
+    // throw zorba exception if we have an error log
+    std::string lErrorMessage = ImapClient::Instance().getError();
+    if (lErrorMessage.size() != 0) {
+      raiseImapError("IMAP0001", lErrorMessage);
+    }
+    
+    int lVectorSize =(int)lFoundSequenceNumbers.size();
+    std::vector<Item> lItemVector;
+    for (int i = 0; i < lVectorSize; i++) {
+      lItemVector.push_back(theModule->getItemFactory()->createLong(lFoundSequenceNumbers[i]));
+    } 
+    
+    return ItemSequence_t(new VectorItemSequence(lItemVector));
+  } catch (EmailException& e) {
+    raiseImapError(e);
+  }
+  return ItemSequence_t(NULL);
+}
+
+//*****************************************************************************
+
+CopyFunction::CopyFunction(const ImapModule* aModule)
+  : ImapFunction(aModule)
+{
+}
+
+ItemSequence_t
+CopyFunction::evaluate(
+  const ExternalFunction::Arguments_t& aArgs,
+  const StaticContext*                          aSctxCtx,
+  const DynamicContext*                         aDynCtx) const
+{
+  try {
+    std::string lHostName;
+    std::string lUserName;
+    std::string lPassword;
+    getHostUserPassword(aArgs, 0, lHostName, lUserName, lPassword);
+    String lMailboxFrom = getOneStringArg(aArgs, 1);
+    String lMailboxTo = getOneStringArg(aArgs, 2);
+    // find out if we are working with uid's instead of sequence numbers.
+    bool lUid = false;
+    Item lItem;
+    
+    Iterator_t arg4_iter = aArgs[4]->getIterator();
+    arg4_iter->open();
+    if (arg4_iter->next(lItem)) {
+      lUid = lItem.getBooleanValue();
+    }
+    arg4_iter->close();
+    Iterator_t arg5_iter = aArgs[5]->getIterator();
+    arg5_iter->open();
+    bool lCopy = false;
+    if (arg5_iter->next(lItem)) {
+      lCopy = lItem.getBooleanValue();
+    }
+    arg5_iter->close();
+    
+    std::string lMessageNumbers = getMessageNumbers(aArgs, 3); 
+    
+    bool lSuccess = ImapClient::Instance().copy(lHostName, lUserName, lPassword, lMailboxFrom.c_str(), lMailboxTo.c_str(), lMessageNumbers, lUid, lCopy);
+    if (!lSuccess) {
+      std::string lErrorMessage = ImapClient::Instance().getError();
+      raiseImapError("IMAP0001", lErrorMessage);
+    }
+    
+  } catch (EmailException& e) {
+    raiseImapError(e);
+  }
+  return ItemSequence_t(NULL);
+}
+
+//*****************************************************************************
+
+FetchEnvelopeFunction::FetchEnvelopeFunction(const ImapModule* aModule)
+  : ImapFunction(aModule)
+{
+}
+
+ItemSequence_t
+FetchEnvelopeFunction::evaluate(
+  const ExternalFunction::Arguments_t& aArgs,
+  const StaticContext*                          aSctxCtx,
+  const DynamicContext*                         aDynCtx) const
+{
+  try {
+    std::string lHostName;
+    std::string lUserName;
+    std::string lPassword;
+    getHostUserPassword(aArgs, 0, lHostName, lUserName, lPassword);
+    String lMailbox = getOneStringArg(aArgs, 1);
+    
+    unsigned long lMessageNumber = getOneMessageNumber(aArgs, 2);  
+    
+    bool lUid = false;
+    Item lItem;
+    Iterator_t arg3_iter = aArgs[3]->getIterator();
+    arg3_iter->open();
+    if (arg3_iter->next(lItem)) {
+      lUid = lItem.getBooleanValue();
+    }
+    arg3_iter->close();
+    
+    Item lParent; 
+    getMessage(lParent,
+      lHostName.c_str(), lUserName.c_str(), lPassword.c_str(),
+      lMailbox.c_str(), lMessageNumber,
+      lUid, true);
+    
+    std::string lErrorMessage = ImapClient::Instance().getError();
+    if (lErrorMessage.size() != 0) {
+      raiseImapError("IMAP0001", lErrorMessage);
+    }
+
+    return ItemSequence_t(new SingletonItemSequence(lParent));
+
+  } catch (EmailException& e) {
+    raiseImapError(e);
+  }
+  return ItemSequence_t(NULL);
+}
+
+//*****************************************************************************
+
+FetchSubjectFunction::FetchSubjectFunction(const ImapModule* aModule)
+  : ImapFunction(aModule)
+{
+}
+
+ItemSequence_t
+FetchSubjectFunction::evaluate(
+  const ExternalFunction::Arguments_t& aArgs,
+  const StaticContext*                          aSctxCtx,
+  const DynamicContext*                         aDynCtx) const
+{
+  try {
+    std::string lHostName;
+    std::string lUserName;
+    std::string lPassword;
+    getHostUserPassword(aArgs, 0, lHostName, lUserName, lPassword);
+    String lMailbox = getOneStringArg(aArgs, 1);
+    unsigned long lMessageNumber = getOneMessageNumber(aArgs, 2);
+    std::string lRawSubject =
+      ImapClient::Instance().fetchSubject(
+        lHostName,
+        lUserName,
+        lPassword,
+        lMailbox.c_str(),
+        lMessageNumber);
+    
+    // decode the subject header because it can contain encoded words
+    std::string lDecodedSubject;
+    decodeHeader(lRawSubject, lDecodedSubject);
+
+    std::string lErrorMessage = ImapClient::Instance().getError();
+    if (lErrorMessage.size() != 0) {
+      raiseImapError("IMAP0001", lErrorMessage);
+    }
+    
+    return ItemSequence_t(new SingletonItemSequence(theModule->getItemFactory()->createString(lDecodedSubject)));
+
+  } catch (EmailException& e) {
+    raiseImapError(e);
+  }
+  return ItemSequence_t(NULL);
+}
+
+//*****************************************************************************
+
+FetchFromFunction::FetchFromFunction(const ImapModule* aModule)
+  : ImapFunction(aModule)
+{
+}
+
+ItemSequence_t
+FetchFromFunction::evaluate(
+  const ExternalFunction::Arguments_t& aArgs,
+  const StaticContext*                          aSctxCtx,
+  const DynamicContext*                         aDynCtx) const
+{
+  try {
+    std::string lHostName;
+    std::string lUserName;
+    std::string lPassword;
+    getHostUserPassword(aArgs, 0, lHostName, lUserName, lPassword);
+    String lMailbox = getOneStringArg(aArgs, 1);
+    unsigned long lMessageNumber = getOneMessageNumber(aArgs, 2);
+    String lResult = ImapClient::Instance().fetchFrom(lHostName, lUserName, lPassword, lMailbox.c_str(), lMessageNumber);
+    
+    std::string lErrorMessage = ImapClient::Instance().getError();
+    if (lErrorMessage.size() != 0) {
+      raiseImapError("IMAP0001", lErrorMessage);
+    }
+    
+    
+    return ItemSequence_t(new SingletonItemSequence(
+                                                    theModule->getItemFactory()->createString(lResult)));
+  } catch (EmailException& e) {
+    raiseImapError(e);
+  }
+  return ItemSequence_t(NULL);
+}
+
+//*****************************************************************************
+
+FetchFlagsFunction::FetchFlagsFunction(const ImapModule* aModule)
+  : ImapFunction(aModule)
+{
+}
+
+ItemSequence_t
+FetchFlagsFunction::evaluate(
+  const ExternalFunction::Arguments_t& aArgs,
+  const StaticContext*                          aSctxCtx,
+  const DynamicContext*                         aDynCtx) const
+{
+  try {
+    std::string lHostName;
+    std::string lUserName;
+    std::string lPassword;
+    getHostUserPassword(aArgs, 0, lHostName, lUserName, lPassword);
+    String lMailbox = getOneStringArg(aArgs, 1);
+    unsigned long lMessageNumber = getOneMessageNumber(aArgs, 2);
+    bool lUid = false;
+    Item lItem;
+    Iterator_t arg3_iter = aArgs[3]->getIterator();
+    arg3_iter->open();
+    if (arg3_iter->next(lItem)) {
+      lUid = lItem.getBooleanValue();
+    }
+    arg3_iter->close();
+    
+    // null parent
+    Item lParent;
+    std::vector<int> lFlags(6, 0);
+    
+    ImapClient::Instance().fetchFlags(lHostName, lUserName, lPassword, lMailbox.c_str(), lMessageNumber,lFlags, lUid);
+    
+    std::string lErrorMessage = ImapClient::Instance().getError();
+    if (lErrorMessage.size() != 0) {
+      raiseImapError("IMAP0001", lErrorMessage);
+    }
+    
+    
+    Item lFlagsItem;
+    createFlagsNode(lParent, lFlagsItem, lFlags, true);
+    
+    return ItemSequence_t(new SingletonItemSequence(lFlagsItem));
+  } catch (EmailException& e) {
+    raiseImapError(e);
+  }
+  return ItemSequence_t(NULL);
+}
+
+//*****************************************************************************
+
+SetFlagsFunction::SetFlagsFunction(const ImapModule* aModule)
+  : ImapFunction(aModule)
+{
+}
+
+ItemSequence_t
+SetFlagsFunction::evaluate(
+  const ExternalFunction::Arguments_t&  aArgs,
+  const StaticContext*                  aSctxCtx,
+  const DynamicContext*                 aDynCtx) const
+{
+  try {
+    std::string lHostName;
+    std::string lUserName;
+    std::string lPassword;
+    getHostUserPassword(aArgs, 0, lHostName, lUserName, lPassword);
+    String lMailbox = getOneStringArg(aArgs, 1);
+    unsigned long lMessageNumber = getOneMessageNumber(aArgs, 2);
+    
+    std::vector<int> lFlags(6, 0);
+    SetFlagsFunction::getFlagsVector(aArgs, lFlags); 
+    
+    bool lUid = false;
+    Item lItem;
+    Iterator_t arg4_iter = aArgs[4]->getIterator();
+    arg4_iter->open();
+    if (arg4_iter->next(lItem)) {
+      lUid = lItem.getBooleanValue();
+    }
+    arg4_iter->close();
+    
+    ImapClient::Instance().setFlags(lHostName, lUserName, lPassword, lMailbox.c_str(), lMessageNumber, lFlags, lUid);
+    
+    std::string lErrorMessage = ImapClient::Instance().getError();
+    if (lErrorMessage.size() != 0) {
+      raiseImapError("IMAP0001", lErrorMessage);
+    }
+    
+  } catch (EmailException& e) {
+    raiseImapError(e);
+  }
+  return ItemSequence_t(NULL);
+}
+
+void
+SetFlagsFunction::getFlagsVector(
+  const ExternalFunction::Arguments_t& aArgs,
+  std::vector<int>& aFlags)
+{
+  Item lFlagsNode;
+  Iterator_t arg3_iter = aArgs[3]->getIterator();
+  arg3_iter->open();
+  arg3_iter->next(lFlagsNode);
+  arg3_iter->close();
+  Iterator_t lChildren = lFlagsNode.getChildren();
+  lChildren->open();
+  Item lChild;
+  while(lChildren->next(lChild)) {
+    Item lNameNode; 
+    lChild.getNodeName(lNameNode);
+    String lName = lNameNode.getStringValue();
+    /* checking for ending of name as it is not sure how the prefix looks like */
+    if (fn::ends_with(lName,"n")) {
+      // seen
+      aFlags[0] = 1; 
+    } else if (fn::ends_with(lName,"ted")) {
+      // deleted
+      aFlags[1] = 1;
+    } else if (fn::ends_with(lName,"ged")) {
+      // flagged
+      aFlags[2] = 1;
+    } else if (fn::ends_with(lName,"red")) {
+      // answered
+      aFlags[3] = 1;
+    } else if (fn::ends_with(lName,"ft")) {
+      // draft
+      aFlags[4] = 1;
+    }
+  }
+}
+
+//*****************************************************************************
+
+FetchUidFunction::FetchUidFunction(const ImapModule* aModule)
+  : ImapFunction(aModule)
+{
+}
+
+ItemSequence_t
+FetchUidFunction::evaluate(
+  const ExternalFunction::Arguments_t& aArgs,
+  const StaticContext*                          aSctxCtx,
+  const DynamicContext*                         aDynCtx) const
+{
+  try {
+    std::string lHostName;
+    std::string lUserName;
+    std::string lPassword;
+    getHostUserPassword(aArgs, 0, lHostName, lUserName, lPassword);
+    String lMailbox = getOneStringArg(aArgs, 1);
+    unsigned long lMessageNumber = getOneMessageNumber(aArgs, 2);
+    unsigned long lResult = ImapClient::Instance().convertNumber(lHostName, lUserName, lPassword, lMailbox.c_str(), lMessageNumber, true);
+    
+    return ItemSequence_t(new SingletonItemSequence(
+                                                    theModule->getItemFactory()->createLong(lResult)));
+  } catch (EmailException& e) {
+    raiseImapError(e);
+  }
+  return ItemSequence_t(NULL);
+}
+
+//*****************************************************************************
+
+FetchMessageSequenceNumberFunction::FetchMessageSequenceNumberFunction(const ImapModule* aModule)
+  : ImapFunction(aModule)
+{
+}
+
+ItemSequence_t
+FetchMessageSequenceNumberFunction::evaluate(
+  const ExternalFunction::Arguments_t& aArgs,
+  const StaticContext*                          aSctxCtx,
+  const DynamicContext*                         aDynCtx) const
+{
+  try {
+    std::string lHostName;
+    std::string lUserName;
+    std::string lPassword;
+    getHostUserPassword(aArgs, 0, lHostName, lUserName, lPassword);
+    String lMailbox = getOneStringArg(aArgs, 1);
+    unsigned long lMessageNumber = getOneMessageNumber(aArgs, 2);
+    unsigned long lResult = ImapClient::Instance().convertNumber(lHostName, lUserName, lPassword, lMailbox.c_str(), lMessageNumber, false);
+    
+    return ItemSequence_t(new SingletonItemSequence(
+                                                    theModule->getItemFactory()->createLong(lResult)));
+  } catch (EmailException& e) {
+    raiseImapError(e);
+  }
+  return ItemSequence_t(NULL);
+}
+
+//*****************************************************************************               
+                                                                                              
+FetchMessageFunction::FetchMessageFunction(const ImapModule* aModule)                       
+  : ImapFunction(aModule)                                                                     
+{                                                                                             
+}      
+
+ItemSequence_t
+FetchMessageFunction::evaluate(
+  const ExternalFunction::Arguments_t& aArgs,
+  const StaticContext*                          aSctxCtx,
+  const DynamicContext*                         aDynCtx) const
+{
+  try {
+    std::string lHostName;  std::string lUserName;  std::string lPassword;
+    getHostUserPassword(aArgs, 0, lHostName, lUserName, lPassword);
+    String lMailbox = getOneStringArg(aArgs, 1);
+    
+    unsigned long lMessageNumber = getOneMessageNumber(aArgs, 2);
+    
+    bool lUid = getOneBoolArg(aArgs, 3);
+    
+    Item lParent;
+    getMessage(lParent,
+      lHostName.c_str(), lUserName.c_str(), lPassword.c_str(),
+      lMailbox.c_str(), lMessageNumber,
+      lUid, false);
+    
+    return ItemSequence_t(new SingletonItemSequence(lParent));
+  } catch (EmailException& e) {
+    raiseImapError(e);
+  }
+  return ItemSequence_t(NULL);
+}
+
+
+// This function is defined here because if defined in imap_function.cpp
+// some header file conflict are raised and it does not compile
+void
+ImapFunction::decodeEncodedWords(
+  const std::string& aRawSubject,
+  std::string& aDecodedSubject) const
+{
+  std::size_t lLength = aRawSubject.length();
+  // if this is not a good format return the raw subject
+  if (lLength < 4 || (aRawSubject.find("=?") != 0 && aRawSubject.find("?=", lLength - 2) != lLength - 2)) {
+    aDecodedSubject = aRawSubject;
+    return;
+  }
+
+  // take out the part between the "=?" and "?="
+  std::string lToSplit = aRawSubject.substr(2, lLength - 4);
+
+  // get the charset
+  std::size_t lQPosTmp;
+  std::size_t lQPos = lToSplit.find("?");
+  if (lQPos == std::string::npos)
+  {
+    aDecodedSubject = aRawSubject;
+    return;
+  }
+  std::string lCharset = lToSplit.substr(0, lQPos);
+  lQPosTmp = lQPos + 1;
+
+  // get the encoding
+  lQPos = lToSplit.find("?", lQPosTmp);
+  if (lQPos == std::string::npos)
+  {
+    aDecodedSubject = aRawSubject;
+    return;
+  }
+  std::string lEncoding = lToSplit.substr(lQPosTmp, lQPos - lQPosTmp);
+  lQPosTmp = lQPos + 1;
+
+  // get the encoded data
+  lQPos = lToSplit.find("?", lQPos + 1);
+  if (lQPos != std::string::npos)
+  {
+    aDecodedSubject = aRawSubject;
+    return;
+  }
+  std::string lData = lToSplit.substr(lQPosTmp);
+
+  // binary
+  if (lEncoding == "B" || lEncoding == "b")
+  {
+    unsigned long lNewLength;
+    void* lNewData = rfc822_base64((unsigned char*)lData.c_str(), lData.length(), &lNewLength);
+    lData = std::string((char *)lNewData, lNewLength);
+  }
+  // quoted
+  else if (lEncoding == "Q" || lEncoding == "q")
+  {
+    unsigned long lNewLength;
+    void* lNewData = rfc822_qprint((unsigned char*)lData.c_str(), lData.length(), &lNewLength);
+    lData = std::string((char *)lNewData, lNewLength);
+    std::replace( lData.begin(), lData.end(), '_', ' ' );
+  }
+  // not a valid encoding?
+  else
+  {
+    aDecodedSubject = aRawSubject;
+    return;
+  }
+
+  // decode this fragment according to the charset
+  toUtf8(lData, lCharset.c_str(), aDecodedSubject);
+}
+
+} /* namespace emailmodule */
+} /* namespace zorba */
+
+#ifdef WIN32
+#  define DLL_EXPORT __declspec(dllexport)
+#else
+#  define DLL_EXPORT __attribute__ ((visibility("default")))
+#endif
+
+extern "C" DLL_EXPORT zorba::ExternalModule* createModule() {
+  return new zorba::emailmodule::ImapModule();
+}

=== added file 'src/com/zorba-xquery/www/modules/email/imap.xq.src/imap.h'
--- src/com/zorba-xquery/www/modules/email/imap.xq.src/imap.h	1970-01-01 00:00:00 +0000
+++ src/com/zorba-xquery/www/modules/email/imap.xq.src/imap.h	2014-04-30 23:07:12 +0000
@@ -0,0 +1,331 @@
+/*
+ * Copyright 2006-2008 The FLWOR Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ZORBA_EMAILMODULE_IMAP_H
+#define ZORBA_EMAILMODULE_IMAP_H
+
+#include <zorba/zorba_string.h>
+
+#include "imap_function.h"
+
+
+namespace zorba { 
+  
+  class ItemFactory;
+  class SerializationItemProvider;
+
+  namespace emailmodule {
+
+//*****************************************************************************
+
+  class StatusFunction : public ImapFunction
+  {
+    public:
+      StatusFunction(const ImapModule* aModule);
+
+      virtual String
+      getLocalName() const { return "status-impl"; }
+  
+      virtual ItemSequence_t 
+      evaluate(const ExternalFunction::Arguments_t& args,
+               const StaticContext* aSctxCtx,
+               const DynamicContext* aDynCtx) const;
+  };
+
+//*****************************************************************************
+
+  class CreateFunction : public ImapFunction
+  {
+    public:
+      CreateFunction(const ImapModule* aModule);
+
+      virtual String
+      getLocalName() const { return "create-impl"; }
+  
+      virtual ItemSequence_t 
+      evaluate(const ExternalFunction::Arguments_t& args,
+               const StaticContext* aSctxCtx,
+               const DynamicContext* aDynCtx) const;
+  };
+
+//*****************************************************************************
+
+  class DeleteFunction : public ImapFunction
+  {
+    public:
+      DeleteFunction(const ImapModule* aModule);
+
+      virtual String
+      getLocalName() const { return "delete-impl"; }
+  
+      virtual ItemSequence_t 
+      evaluate(const ExternalFunction::Arguments_t& args,
+               const StaticContext* aSctxCtx,
+               const DynamicContext* aDynCtx) const;
+  };
+
+//*****************************************************************************
+
+  class RenameFunction : public ImapFunction
+  {
+    public:
+      RenameFunction(const ImapModule* aModule);
+
+      virtual String
+      getLocalName() const { return "rename-impl"; }
+
+      virtual ItemSequence_t
+      evaluate(const ExternalFunction::Arguments_t& args,
+               const StaticContext* aSctxCtx,
+               const DynamicContext* aDynCtx) const;
+  };
+
+//*****************************************************************************
+
+  class ListFunction : public ImapFunction
+  {
+    public:
+      ListFunction(const ImapModule* aModule);
+
+      virtual String
+      getLocalName() const { return "list-impl"; }
+
+      virtual ItemSequence_t
+      evaluate(const ExternalFunction::Arguments_t& args,
+               const StaticContext* aSctxCtx,
+               const DynamicContext* aDynCtx) const;
+  };
+
+//*****************************************************************************
+
+  class SubscribeFunction : public ImapFunction
+  {
+    public:
+      SubscribeFunction(const ImapModule* aModule);
+
+      virtual String
+      getLocalName() const { return "subscribe-impl"; }
+
+      virtual ItemSequence_t
+      evaluate(const ExternalFunction::Arguments_t& args,
+               const StaticContext* aSctxCtx,
+               const DynamicContext* aDynCtx) const;
+  };
+
+//*****************************************************************************
+
+  class UnsubscribeFunction : public ImapFunction
+  {
+    public:
+      UnsubscribeFunction(const ImapModule* aModule);
+
+      virtual String
+      getLocalName() const { return "unsubscribe-impl"; }
+
+      virtual ItemSequence_t
+      evaluate(const ExternalFunction::Arguments_t& args,
+               const StaticContext* aSctxCtx,
+               const DynamicContext* aDynCtx) const;
+  };
+
+//*****************************************************************************
+
+  class ExpungeFunction : public ImapFunction
+  {
+    public:
+      ExpungeFunction(const ImapModule* aModule);
+
+      virtual String
+      getLocalName() const { return "expunge-impl"; }
+
+      virtual ItemSequence_t
+      evaluate(const ExternalFunction::Arguments_t& args,
+               const StaticContext* aSctxCtx,
+               const DynamicContext* aDynCtx) const;
+  };
+
+//*****************************************************************************
+
+  class SearchFunction : public ImapFunction
+  {
+    public:
+      SearchFunction(const ImapModule* aModule);
+
+      virtual String
+      getLocalName() const { return "search-impl"; }
+
+      virtual ItemSequence_t
+      evaluate(const ExternalFunction::Arguments_t& args,
+               const StaticContext* aSctxCtx,
+               const DynamicContext* aDynCtx) const;
+  };
+
+//*****************************************************************************
+
+  class CopyFunction : public ImapFunction
+  {
+    public:
+      CopyFunction(const ImapModule* aModule);
+
+      virtual String
+      getLocalName() const { return "copy-impl"; }
+
+      virtual ItemSequence_t
+      evaluate(const ExternalFunction::Arguments_t& args,
+               const StaticContext* aSctxCtx,
+               const DynamicContext* aDynCtx) const;
+  };
+
+//*****************************************************************************
+
+  class FetchEnvelopeFunction : public ImapFunction
+  {
+    public:
+      FetchEnvelopeFunction(const ImapModule* aModule);
+
+      virtual String
+      getLocalName() const { return "fetch-envelope-impl"; }
+
+      virtual ItemSequence_t
+      evaluate(const ExternalFunction::Arguments_t& args,
+               const StaticContext* aSctxCtx,
+               const DynamicContext* aDynCtx) const;
+  
+  
+  };
+
+//*****************************************************************************
+
+  class FetchFlagsFunction : public ImapFunction
+  {
+    public:
+      FetchFlagsFunction(const ImapModule* aModule);
+
+      virtual String
+      getLocalName() const { return "fetch-flags-impl"; }
+
+      virtual ItemSequence_t
+      evaluate(const ExternalFunction::Arguments_t& args,
+               const StaticContext* aSctxCtx,
+               const DynamicContext* aDynCtx) const;
+
+
+  };
+
+//*****************************************************************************
+
+  class SetFlagsFunction : public ImapFunction
+  {
+    public:
+      SetFlagsFunction(const ImapModule* aModule);
+
+      virtual String
+      getLocalName() const { return "set-flags-impl"; }
+
+      virtual ItemSequence_t
+      evaluate(const ExternalFunction::Arguments_t& args,
+               const StaticContext* aSctxCtx,
+               const DynamicContext* aDynCtx) const;
+
+      static void 
+      getFlagsVector(const ExternalFunction::Arguments_t& aArgs, std::vector<int>& aFlags);
+  };
+
+//*****************************************************************************
+
+  class FetchSubjectFunction : public ImapFunction
+  {
+    public:
+      FetchSubjectFunction(const ImapModule* aModule);
+
+      virtual String
+      getLocalName() const { return "fetch-subject-impl"; }
+
+      virtual ItemSequence_t
+      evaluate(const ExternalFunction::Arguments_t& args,
+               const StaticContext* aSctxCtx,
+               const DynamicContext* aDynCtx) const;
+  };
+
+//*****************************************************************************
+
+  class FetchFromFunction: public ImapFunction
+  {
+    public:
+      FetchFromFunction(const ImapModule* aModule);
+
+      virtual String
+      getLocalName() const { return "fetch-from-impl"; }
+
+      virtual ItemSequence_t
+      evaluate(const ExternalFunction::Arguments_t& args,
+               const StaticContext* aSctxCtx,
+               const DynamicContext* aDynCtx) const;
+  };
+
+//*****************************************************************************
+
+  class FetchUidFunction: public ImapFunction
+  {
+    public:
+      FetchUidFunction(const ImapModule* aModule);
+
+      virtual String
+      getLocalName() const { return "fetch-uid-impl"; }
+
+      virtual ItemSequence_t
+      evaluate(const ExternalFunction::Arguments_t& args,
+               const StaticContext* aSctxCtx,
+               const DynamicContext* aDynCtx) const;
+  };
+
+//*****************************************************************************
+
+  class FetchMessageSequenceNumberFunction: public ImapFunction
+  {
+    public:
+      FetchMessageSequenceNumberFunction(const ImapModule* aModule);
+
+      virtual String
+      getLocalName() const { return "fetch-message-sequence-number-impl"; }
+
+      virtual ItemSequence_t
+      evaluate(const ExternalFunction::Arguments_t& args,
+               const StaticContext* aSctxCtx,
+               const DynamicContext* aDynCtx) const;
+  };
+
+//*****************************************************************************
+
+  class FetchMessageFunction : public ImapFunction
+  {
+    public:
+      FetchMessageFunction(const ImapModule* aModule);
+
+      virtual String
+      getLocalName() const { return "fetch-message-impl"; }
+
+      virtual ItemSequence_t
+      evaluate(const ExternalFunction::Arguments_t& args,
+               const StaticContext* aSctxCtx,
+               const DynamicContext* aDynCtx) const;
+  };
+
+  
+} /* namespace emailmodule */
+} /* namespace zorba */
+
+#endif /* ZORBA_EMAILMODULE_FILE_H */

=== added file 'src/com/zorba-xquery/www/modules/email/imap.xq.src/imap_function.cpp'
--- src/com/zorba-xquery/www/modules/email/imap.xq.src/imap_function.cpp	1970-01-01 00:00:00 +0000
+++ src/com/zorba-xquery/www/modules/email/imap.xq.src/imap_function.cpp	2014-04-30 23:07:12 +0000
@@ -0,0 +1,957 @@
+/*
+ * Copyright 2006-2008 The FLWOR Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <algorithm>
+#include <iostream>
+#include <map>
+#include <sstream>
+
+#include <unicode/ucnv.h>
+#include <unicode/ustring.h>
+
+#include <zorba/diagnostic_list.h>
+#include <zorba/iterator.h>
+#include <zorba/item_sequence.h>
+#include <zorba/user_exception.h>
+#include <zorba/util/base64_util.h>
+#include <zorba/zorba.h>
+
+#include "imap_function.h"
+#include "imap_module.h"
+#include "imap_client.h"
+#include "email_exception.h"
+
+namespace zorba { namespace emailmodule {
+
+const char* ImapFunction::SCHEMA_NAMESPACE = "http://www.zorba-xquery.com/modules/email";;  
+const char* ImapFunction::SCHEMA_PREFIX = "email";  
+
+ImapFunction::ImapFunction(const ImapModule* aModule)
+  : theModule(aModule)
+{
+}
+
+ImapFunction::~ImapFunction()
+{
+}
+
+void
+ImapFunction::raiseImapError(
+  EmailException& e) const
+{
+  std::string lCode;
+  if (e.get_localname() == "CONNECTION_ERROR") {
+    lCode = "IMAP0002";
+  }
+  else if (e.get_localname() == "WRONG_ID") {
+    lCode = "IMAP0003";
+  }
+  else {
+    lCode = "IMAP0001";
+  }
+  raiseImapError(lCode, e.get_message());
+}
+
+void
+ImapFunction::raiseImapError(
+      const std::string& qName,
+      const std::string& message) const
+{
+  Item lQName = theModule->getItemFactory()->createQName(getURI(), "imap", qName);
+  throw USER_EXCEPTION(lQName, message);
+}
+
+String
+ImapFunction::getURI() const
+{
+  return theModule->getURI();
+}
+
+void 
+ImapFunction::getHostUserPassword(
+  const ExternalFunction::Arguments_t& aArgs,
+  int aPos,
+  std::string& aHost,
+  std::string& aUserName,
+  std::string& aPassword) const
+{
+  Item lNode;
+  Iterator_t args_iter = aArgs[aPos]->getIterator();
+  args_iter->open();
+  args_iter->next(lNode);
+  args_iter->close();
+  Iterator_t lChildren = lNode.getChildren();
+  lChildren->open();
+  Item lChild;
+  lChildren->next(lChild);
+  aHost = lChild.getStringValue().c_str();
+  lChildren->next(lChild);
+  aUserName = lChild.getStringValue().c_str();
+  lChildren->next(lChild);
+  aPassword = lChild.getStringValue().c_str();
+  lChildren->close();  
+}
+
+String
+ImapFunction::getOneStringArg(
+  const ExternalFunction::Arguments_t& aArgs,
+  int aPos) const
+{
+  Item lItem;
+  Iterator_t args_iter = aArgs[aPos]->getIterator();
+  args_iter->open();
+  args_iter->next(lItem);
+  args_iter->close();
+  return lItem.getStringValue();
+}
+
+std::string
+ImapFunction::getMessageNumbers(
+  const ExternalFunction::Arguments_t& aArgs,
+  int aPos) const
+{
+  Item lItem;
+  std::stringstream lMessageNumbers;
+  Iterator_t args_iter = aArgs[aPos]->getIterator();
+  args_iter->open();
+  args_iter->next(lItem);
+  lMessageNumbers << lItem.getStringValue().c_str();
+  while(args_iter->next(lItem)) {
+    lMessageNumbers << "," << lItem.getStringValue().c_str();
+  }
+  args_iter->close();
+  return lMessageNumbers.str(); 
+}
+
+unsigned long
+ImapFunction::getOneMessageNumber(
+  const ExternalFunction::Arguments_t& aArgs,
+  int aPos) const
+{
+  Item lItem;
+  Iterator_t args_iter = aArgs[aPos]->getIterator();
+  args_iter->open();
+  args_iter->next(lItem);
+  args_iter->close();
+  return lItem.getLongValue();
+}
+
+bool
+ImapFunction::getOneBoolArg(
+  const ExternalFunction::Arguments_t& aArgs,
+  int aPos) const
+{
+  Item lItem;
+  Iterator_t args_iter = aArgs[aPos]->getIterator();
+  args_iter->open();
+  args_iter->next(lItem);
+  args_iter->close();
+  return lItem.getBooleanValue();
+}
+
+std::string
+ImapFunction::getDateTime(const std::string& aCClientDateTime) const
+{
+  std::stringstream lResult;    
+  std::stringstream lDateTimeStream(aCClientDateTime);
+  std::string lBuffer;
+  std::vector<std::string> lTokens;
+  
+  while (lDateTimeStream >> lBuffer) { 
+    lTokens.push_back(lBuffer);
+  }
+
+  // build up map for Months
+  std::string lMonths = "JanFebMarAprMayJunJulAugSepOctNovDec";
+  size_t lMonthNumber = lMonths.find(lTokens[2]);
+  size_t lTokensShift = 0;
+  if (lMonthNumber == std::string::npos) {
+    // if the month is not there, day of week is possibly missing, 
+    // shift tokens by one and retry
+    lTokensShift = -1;
+    lMonthNumber = lMonths.find(lTokens[2 + lTokensShift]);
+    if (lMonthNumber == std::string::npos) {
+      // now, we are really in trouble, something is wrong
+      Item lQName = theModule->getItemFactory()
+                      ->createQName(SCHEMA_NAMESPACE, "XPTY0004");
+      throw USER_EXCEPTION(
+              lQName, 
+              "Error while processing month in date of email message");
+    }
+  }
+
+  // YYYY-MM-DDThh:mm:ss, first push YYYY
+  lResult << lTokens[3 + lTokensShift] << "-";
+  // then push MM
+
+  lMonthNumber = lMonthNumber/3 + 1;
+  // make sure its MM and not just <
+  if (lMonthNumber < 10) {
+    lResult << 0;
+  }  
+  lResult << lMonthNumber << "-";
+  
+  if (lTokens[1 + lTokensShift].size() == 1) {
+    lResult << 0;
+  }
+  lResult << lTokens[1 + lTokensShift] << "T";
+  // now hh:mm:ss
+  lResult << lTokens[4 + lTokensShift].substr(0,2) << ":" 
+    << lTokens[4 + lTokensShift].substr(3,2) << ":" 
+    << lTokens[4 + lTokensShift].substr(6,2);
+
+
+  return lResult.str();
+  
+}
+
+std::string
+ImapFunction::getContentType(
+  const unsigned short aType,
+  const char* aSubtype) const
+{
+  std::stringstream lType;
+  switch (aType) {
+    // Text
+    case 0 : 
+      lType << "text";
+    break;
+    case 1 : 
+      lType << "multipart";
+    break;
+    case 2 : 
+      lType << "message";
+    break;
+    case 3 : 
+      lType << "application";
+    break;
+    case 4 :
+      lType << "audio";
+    break;
+    case 5 :
+      lType << "image";
+    break;
+    case 6 :
+      lType << "video";
+    break;
+    case 7 : 
+      lType << "model";
+    break;
+    case 8 :
+      lType << "other";
+    break;
+  }  
+  std::string lSubType(aSubtype); 
+  std::transform(lSubType.begin(), lSubType.end(), lSubType.begin(), tolower);
+  lType << "/" << lSubType; 
+  return lType.str();
+
+}
+
+std::string
+ImapFunction::getEncoding(const unsigned short aEncoding) const
+{
+  std::stringstream lEncoding;
+  switch (aEncoding) {
+    case 0 :
+      lEncoding << "ENC7BIT";
+    break;
+    case 1 : 
+      lEncoding << "ENC8BIT";
+    break;
+    case 2 :
+      lEncoding << "ENCBINARY";
+    break;
+    case 3 : 
+      lEncoding << "ENCBASE64";
+    break;
+    case 4 :
+      lEncoding << "ENCQUOTEDPRINTABLE";
+    break;
+    case 5 :
+      lEncoding << "ENCOTHER";
+    break;
+    default : lEncoding << "ENCOTHER"; 
+
+
+  }
+  return lEncoding.str();
+}
+
+void
+ImapFunction::createFlagsNode(
+  Item& aParent,
+  Item& aFlags,
+  std::vector<int>& aFlagsVector,
+  const bool aQualified) const
+{
+  NsBindings ns_binding;
+  ns_binding.push_back(std::pair<String, String>(SCHEMA_PREFIX, SCHEMA_NAMESPACE));
+  
+  // if aParent is null, then we want to have the flags node qualified (so that it can be shema validated)
+  Item lFlagsName;
+  lFlagsName = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, SCHEMA_PREFIX, "flags");
+  Item lFlagsType = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE,  "flagsType");
+  aFlags = theModule->getItemFactory()->createElementNode(aParent, lFlagsName, lFlagsType, false, false, ns_binding);
+
+  std::string lFlagName;
+  for (int i = 0; i < 5; ++i) {
+    int lFlagNumber = aFlagsVector[i];
+    if (lFlagNumber == 1) {
+      switch (i) {
+      case 0:
+        lFlagName = "seen";
+        break;
+      case 1 :
+        lFlagName = "deleted";
+        break;
+      case 2 :
+        lFlagName = "flagged";
+        break;
+      case 3 :
+        lFlagName = "answered";
+        break;
+      case 4 :
+        lFlagName = "draft";
+        break;
+      }
+      
+      Item lOneFlagName = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, SCHEMA_PREFIX, lFlagName);
+      Item lOneFlagType = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, "emptyType");
+      Item lOneFlag = theModule->getItemFactory()->createElementNode(aFlags, lOneFlagName, lOneFlagType, false, true, ns_binding);
+    }
+  }
+}
+
+void
+ImapFunction::createInnerNodeWithText(
+  Item& aParent,
+  const std::string& aNamespace,
+  const std::string& aPrefix,
+  const std::string& aName,
+  const std::string& aTypeNamespace,
+  const std::string& aType,
+  const std::string& aContent) const
+{
+  NsBindings null_binding;
+  Item lName = theModule->getItemFactory()->createQName(aNamespace, aPrefix, aName);
+  Item lType = theModule->getItemFactory()->createQName(aTypeNamespace,  aType);
+  Item lItem = theModule->getItemFactory()->createElementNode(aParent, lName, lType, false, false, null_binding);
+  theModule->getItemFactory()->createTextNode(lItem, String(aContent));
+}  
+
+void
+ImapFunction::createContentNode(
+  Item& aParent,
+  const std::string& aContent,
+  const std::string& aContentType,
+  const std::string& aCharset,
+  const std::string& aContentTransferEncoding,
+  const std::string& aContentDisposition,
+  const std::string& aContentDispositionFilename,
+  const std::string& aContentDispositionModificationDate,
+  const std::string& aContentId) const
+{  
+  Item lNullItem;
+   
+  NsBindings null_binding;
+  Item lName = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, SCHEMA_PREFIX, "content");
+  Item lType = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, "contentType" );
+  Item lItem = theModule->getItemFactory()->createElementNode(aParent, lName, lType, false, false, null_binding);
+  
+  createContentTypeAttributes(lItem, aContentType, aCharset, aContentTransferEncoding, aContentDisposition, aContentDispositionFilename, aContentDispositionModificationDate);
+
+  if (aContentId.length() > 1) {
+    Item lContentIdName = theModule->getItemFactory()->createQName("", "content-id");
+    Item lContentIdType = theModule->getItemFactory()->createQName("http://www.w3.org/2001/XMLSchema";, "string");
+    Item lContentIdText = theModule->getItemFactory()->createTextNode(lNullItem, String(aContentId));
+    theModule->getItemFactory()->createAttributeNode(lItem, lContentIdName, lContentIdType, lContentIdText);
+  }  
+
+  theModule->getItemFactory()->createTextNode(lItem, String(aContent));
+}
+
+void 
+ImapFunction::createEmailAddressNode(
+  Item& aParent,
+  const std::string& aName,
+  const char* aPersonal,
+  const char* aMailbox,
+  const char* aHost) const
+{
+  if ((aMailbox) && (aHost)) {
+    // mailbox and host needs to be available, otherwise broken
+    Item lType = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, "emailAddress");
+    Item lName = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, SCHEMA_PREFIX,  aName);
+
+    NsBindings ns_binding;
+    ns_binding.push_back(std::pair<String, String>(SCHEMA_PREFIX, SCHEMA_NAMESPACE));
+   
+    Item lItem = theModule->getItemFactory()->createElementNode(aParent, lName, lType, false, false, ns_binding);
+    if (aPersonal) {
+      std::string lDecodedPersonal;
+      decodeHeader(std::string(aPersonal), lDecodedPersonal);
+      createInnerNodeWithText(
+          lItem, SCHEMA_NAMESPACE, SCHEMA_PREFIX, "name", 
+          "http://www.w3.org/2001/XMLSchema";, "string", lDecodedPersonal);
+    }
+
+    std::string lDecodedMailbox, lDecodedHost;
+    decodeHeader(std::string(aMailbox), lDecodedMailbox);
+    decodeHeader(std::string(aHost), lDecodedHost);
+    createInnerNodeWithText(
+        lItem, SCHEMA_NAMESPACE, SCHEMA_PREFIX, "email", SCHEMA_NAMESPACE, 
+        "emailAddressType", lDecodedMailbox + "@" + lDecodedHost);  
+  }
+}
+
+void 
+ImapFunction::createRecipientNode(
+  Item& aParent,
+  const std::string& aName,
+  const char* aPersonal,
+  const char* aMailbox,
+  const char* aHost) const
+{                    
+  if (aMailbox && aHost) {
+    // mailbox and host needs to be available, otherwise bcc
+    Item lType = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, "recipientType");                                                                    
+    Item lName = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, SCHEMA_PREFIX, "recipient");                           
+    
+    NsBindings ns_binding;
+    ns_binding.push_back(std::pair<String, String>(SCHEMA_PREFIX, SCHEMA_NAMESPACE));
+   
+    Item lItem = theModule->getItemFactory()->createElementNode(aParent, lName, lType, false, false, ns_binding); 
+    createEmailAddressNode(lItem, aName, aPersonal, aMailbox, aHost);
+  }
+}
+
+void 
+ImapFunction::createContentTypeAttributes(
+  Item& aParent,
+  const std::string& aContentType,
+  const std::string& aCharset,
+  const std::string& aContentTransferEncoding,
+  const std::string& aContentDisposition,
+  const std::string& aContentDispositionFilename,
+  const std::string& aContentDispositionModificationDate) const
+{
+  Item lNullItem;
+  /* build the value attribute */
+  Item lContentTypeName = theModule->getItemFactory()->createQName("", "contentType");
+  Item lContentTypeType = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, "contentTypeValue");
+  Item lContentTypeText = theModule->getItemFactory()->createTextNode(lNullItem, String(aContentType));
+  theModule->getItemFactory()->createAttributeNode(aParent, lContentTypeName, lContentTypeType, lContentTypeText);
+
+  /* build the charset attribute */
+  Item lCharsetName = theModule->getItemFactory()->createQName("", "charset");
+  Item lCharsetType = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, "string");
+  Item lCharsetText = theModule->getItemFactory()->createTextNode(lNullItem, String(aCharset));
+  theModule->getItemFactory()->createAttributeNode(aParent, lCharsetName, lCharsetType, lCharsetText);
+
+  /* build the contentTransferEncoding attribute */
+  Item lContentTransferName = theModule->getItemFactory()->createQName("", "contentTransferEncoding");
+  Item lContentTransferType = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, "cteType");
+  Item lContentTransferText = theModule->getItemFactory()->createTextNode(lNullItem, String(aContentTransferEncoding));
+  theModule->getItemFactory()->createAttributeNode(aParent, lContentTransferName, lContentTransferType, lContentTransferText);
+  /* build the contentDisposition attribute */
+  
+  if (aContentDisposition.length() > 2) {
+  
+    Item lContentDispositionName = theModule->getItemFactory()->createQName("", "contentDisposition");
+    Item lContentDispositionType = theModule->getItemFactory()->createQName("http://www.w3.org/2001/XMLSchema";, "string");
+    Item lContentDispositionText = theModule->getItemFactory()->createTextNode(lNullItem, String(aContentDisposition));
+    theModule->getItemFactory()->createAttributeNode(aParent, lContentDispositionName, lContentDispositionType, lContentDispositionText);
+    if (aContentDispositionFilename.length() > 1) {
+    /* build the contentDispositionFilename attribute */
+      Item lContentDispositionFilenameName = theModule->getItemFactory()->createQName("", "contentDisposition-filename");
+      Item lContentDispositionFilenameType = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, "string");
+      Item lContentDispositionFilenameText = theModule->getItemFactory()->createTextNode(lNullItem, String(aContentDispositionFilename));
+      theModule->getItemFactory()->createAttributeNode(aParent, lContentDispositionFilenameName, lContentDispositionFilenameType, lContentDispositionFilenameText);
+    }
+    if (aContentDispositionModificationDate.length() > 2) { 
+      /* build the contentDispositionModificationDate attribute */ 
+      Item lContentDispositionModificationDateName = theModule->getItemFactory()->createQName("", "contentDisposition-modification-date");
+      Item lContentDispositionModificationDateType = theModule->getItemFactory()->createQName("http://www.w3.org/2001/XMLSchema";, "string");
+      Item lContentDispositionModificationDateText = theModule->getItemFactory()->createTextNode(lNullItem, String(getDateTime(aContentDispositionModificationDate)));
+      theModule->getItemFactory()->createAttributeNode(aParent, lContentDispositionModificationDateName, lContentDispositionModificationDateType, lContentDispositionModificationDateText);
+    }
+  }
+}
+
+void
+ImapFunction::getMessage(
+  Item& aParent,
+  const std::string& aHostName, 
+  const std::string& aUserName, 
+  const std::string& aPassword, 
+  const std::string& aMailbox, 
+  const unsigned long aMessageNumber, 
+  const bool aUid, 
+  const bool aOnlyEnvelope) const
+{
+  std::vector<int> lFlags(6,0);
+  ENVELOPE* lEnvelope;
+  BODY* lBody;
+  if (aOnlyEnvelope) {
+    // only fetch envelope
+    lEnvelope =  ImapClient::Instance().fetchEnvelope(aHostName, aUserName, aPassword, aMailbox, aMessageNumber, lFlags, aUid);
+  } else {
+    // the flags vector in the imap client will be filled by this call, so clear it
+    lEnvelope = ImapClient::Instance().fetchStructure(aHostName, aUserName, aPassword, aMailbox, &lBody, aMessageNumber, aUid, lFlags);
+  }
+    
+  NsBindings ns_binding;
+  ns_binding.push_back(std::pair<String, String>(SCHEMA_PREFIX, SCHEMA_NAMESPACE));
+    
+  Item lEnvelopeItem;
+  std::string lErrorMessage = ImapClient::Instance().getError();
+  if (lErrorMessage.size() != 0) {
+    Item lQName = ImapModule::getItemFactory()->createQName(ImapModule::getURIString(), "imap", "IMAP0001");
+    throw USER_EXCEPTION(lQName, lErrorMessage);
+  }
+
+  // First construct the envelope (depending on aOnlyEnvelope we may be finished then)
+  // Important: if we only want the envelope, then the envelope MUST be qualified (being the root of the DOM)
+  Item lEnvelopeName;
+  if (aOnlyEnvelope) {
+    lEnvelopeName = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, SCHEMA_PREFIX, "envelope");
+  } else {
+    lEnvelopeName = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, SCHEMA_PREFIX, "envelope");
+  }  
+  Item lEnvelopeType = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, SCHEMA_PREFIX, "envelopeType");
+    
+  Item lNullItem;
+  // if we only want the envelope, then create it with a null parent, else create the message and use it as parent
+  if (aOnlyEnvelope) {
+    lEnvelopeItem =  theModule->getItemFactory()->createElementNode(lNullItem, lEnvelopeName, lEnvelopeType, false, false, ns_binding);
+  } else {
+    Item lMessageName = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, SCHEMA_PREFIX, "message");
+    Item lMessageType = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, SCHEMA_PREFIX, "messageType");
+    aParent =  theModule->getItemFactory()->createElementNode(lNullItem, lMessageName, lMessageType, false, false, ns_binding);
+    lEnvelopeItem =  theModule->getItemFactory()->createElementNode(aParent, lEnvelopeName, lEnvelopeType, false, false, ns_binding);
+  }
+    
+  // create the remail node if needed
+  if (lEnvelope->remail) {
+    std::string lDecodedRemail;
+    decodeHeader(std::string(lEnvelope->remail), lDecodedRemail);
+    createInnerNodeWithText(
+        lEnvelopeItem, SCHEMA_NAMESPACE, SCHEMA_PREFIX,  "remail",
+        "http://www.w3.org/2001/XMLSchema";, "string", lDecodedRemail);
+  }
+  // create the date node if needed
+  if (lEnvelope->date) {
+    createInnerNodeWithText(
+      lEnvelopeItem,
+      SCHEMA_NAMESPACE,
+      SCHEMA_PREFIX,
+      "date",
+      "http://www.w3.org/2001/XMLSchema";,
+      "string",
+      getDateTime(reinterpret_cast<const char*>(lEnvelope->date)));
+  }
+  // create from node if needed
+  if (lEnvelope->from) {
+    createEmailAddressNode(lEnvelopeItem, "from", lEnvelope->from->personal, lEnvelope->from->mailbox, lEnvelope->from->host);
+  }
+  // create sender node if needed  
+  if (lEnvelope->sender) {
+    createEmailAddressNode(lEnvelopeItem, "sender", lEnvelope->sender->personal, lEnvelope->sender->mailbox, lEnvelope->sender->host);
+  }
+  // create replyTo node if needed
+  if (lEnvelope->reply_to) {
+    createEmailAddressNode(lEnvelopeItem, "replyTo", lEnvelope->reply_to->personal, lEnvelope->reply_to->mailbox, lEnvelope->reply_to->host);
+  }
+  // create subject node
+  if (lEnvelope->subject) {
+    std::string lSubject = lEnvelope->subject;
+    std::string lDecodedSubject;
+    decodeHeader(lSubject, lDecodedSubject);
+    createInnerNodeWithText(lEnvelopeItem, SCHEMA_NAMESPACE, SCHEMA_PREFIX,  "subject", "http://www.w3.org/2001/XMLSchema";, "string", lDecodedSubject);
+  }
+    
+  ADDRESS* lRecipients;
+  if (lEnvelope->to) {
+    createRecipientNode(lEnvelopeItem, "to", lEnvelope->to->personal, lEnvelope->to->mailbox, lEnvelope->to->host);
+    lRecipients = lEnvelope->to;
+    while ((lRecipients = lRecipients->next)) {
+      createRecipientNode(lEnvelopeItem, "to", lEnvelope->to->personal, lEnvelope->to->mailbox, lEnvelope->to->host);
+    }
+  }
+    
+  if (lEnvelope->cc) {
+    createRecipientNode(lEnvelopeItem, "cc", lEnvelope->cc->personal, lEnvelope->cc->mailbox, lEnvelope->cc->host);
+    lRecipients = lEnvelope->cc;
+    while ((lRecipients = lRecipients->next)) {
+      createRecipientNode(lEnvelopeItem, "cc", lEnvelope->cc->personal, lEnvelope->cc->mailbox, lEnvelope->cc->host);
+    }
+  }
+    
+  if ((lRecipients = lEnvelope->bcc)) {
+    createRecipientNode(lEnvelopeItem, "bcc", lEnvelope->bcc->personal, lEnvelope->bcc->mailbox, lEnvelope->bcc->host);
+    while ((lRecipients = lRecipients->next)) {
+      createRecipientNode(lEnvelopeItem, "bcc", lEnvelope->bcc->personal, lEnvelope->bcc->mailbox, lEnvelope->bcc->host);
+    }
+  }
+    
+  // create messageId node
+  if (lEnvelope->message_id) {
+    createInnerNodeWithText(lEnvelopeItem,  SCHEMA_NAMESPACE, SCHEMA_PREFIX,  "messageId", "http://www.w3.org/2001/XMLSchema";, "string", lEnvelope->message_id);
+  }
+  Item lFlagsItem;
+  // create flags node
+  createFlagsNode(lEnvelopeItem, lFlagsItem, lFlags, false);
+    
+  // if we only want the envelope, then here is a good place to stop
+  if (aOnlyEnvelope) {
+    aParent = lEnvelopeItem;
+    return;
+  } 
+    
+  // if we want the whole message, then build it together
+    
+  // <email:mimeVersion>1.0</email:mimeVersion>
+  createInnerNodeWithText(aParent,  SCHEMA_NAMESPACE, SCHEMA_PREFIX, "mimeVersion", "http://www.w3.org/2001/XMLSchema";, "string", "1.0");
+        
+  // make a tolower version of the subtype
+  std::string lSubType(lBody->subtype);
+  std::transform(lSubType.begin(), lSubType.end(), lSubType.begin(), tolower);
+    
+  // creating the <body> node
+  Item lBodyName = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, SCHEMA_PREFIX, "body");
+  Item lBodyType = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, SCHEMA_PREFIX, "bodyTypeChoice");
+  Item lBodyItem = theModule->getItemFactory()->createElementNode(aParent, lBodyName, lBodyType, false, false, ns_binding); 
+  // in case of non-multipart, just add the body to the message
+    
+  Item lMultipartParentName = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, SCHEMA_PREFIX, "multipart");
+  Item lMultipartParentType = theModule->getItemFactory()->createQName(SCHEMA_NAMESPACE, SCHEMA_PREFIX, "multipartType");
+  Item lMultipartParent; 
+  // using a vector instead of a stack, because including stack will clash with the c-client include ... 
+  std::vector<BODY*> lBodies;
+  lBodies.push_back(lBody);
+  std::vector<Item> lParents;
+  lParents.push_back(lBodyItem);
+  std::vector<std::string> lSections;
+  lSections.push_back("");  
+    
+  // make sure that the special case of a completely non-multipart message is handled correctly
+  bool lNoMultipart = false;
+  if (lBody->type != TYPEMULTIPART) {
+    lNoMultipart = true;
+  }
+    
+  BODY* lCurrentBody;
+  Item lCurrentParent;
+  std::string lCurrentSection; 
+  // iterate and create all nodes (doing this recursive would have been nicer, but seems impossible without making a function containing a c-client structure in its signature, which seems impossible)
+  while (lBodies.size() > 0) {
+    lCurrentBody = lBodies.front();
+    lCurrentParent = lParents.front();
+    lCurrentSection = lSections.front(); 
+    lSections.erase(lSections.begin());
+    lParents.erase(lParents.begin()); 
+    lBodies.erase(lBodies.begin());
+    // get different attributes that we will need in any case, regardless if this is a content or multipart item
+    std::string lContentType = getContentType(lCurrentBody->type, lCurrentBody->subtype);
+    std::string lContentDisposition = "";
+    if (lCurrentBody->disposition.type != NIL) {
+      lContentDisposition = cpystr(lCurrentBody->disposition.type);
+    }  
+    std::string lContentDispositionFilename = "";
+    std::string lContentDispositionModificationDate = "";
+      
+    PARAMETER* lCurrentParameter = lCurrentBody->disposition.parameter;
+    while (lCurrentParameter != NIL) {
+      std::string lAttribute = lCurrentParameter->attribute;
+      std::transform(lAttribute.begin(), lAttribute.end(), lAttribute.begin(), ::tolower);
+      if (!std::string("filename").compare(lAttribute)) {
+        lContentDispositionFilename = cpystr(lCurrentParameter->value);
+      } else if (!std::string("filename*0").compare(lAttribute)) {
+        // TODO this is a hack that works for most cases.
+        // See: http://tools.ietf.org/html/rfc2184 [Page 3]
+        lContentDispositionFilename = cpystr(lCurrentParameter->value);
+      }  else if (!std::string("modification-date").compare(lAttribute)) {
+        lContentDispositionModificationDate = cpystr(lCurrentParameter->value);
+      }  
+        
+      lCurrentParameter = lCurrentParameter->next;
+    }  
+      
+    if (lCurrentBody->type != TYPEMULTIPART) {
+      std::string lContentId = "";
+      char * lId = lCurrentBody->id;
+        
+      if (lId != NIL) {
+        lContentId = cpystr(lId);
+      }
+        
+      std::string lSubType(lCurrentBody->subtype);                                                                  
+      std::transform(lSubType.begin(), lSubType.end(), lSubType.begin(), tolower);
+      // make sure that we haven't got a empty string (happens if there is no multipart in this message)
+      if (lCurrentSection.size() != 0) {
+        lCurrentSection.erase(lCurrentSection.end() - 1);
+      }
+        
+      std::string lBodyContent = ImapClient::Instance().fetchBodyFull(aHostName, aUserName, aPassword, aMailbox, aMessageNumber, lNoMultipart ? "1" : lCurrentSection, aUid);
+
+        // reading charset from email
+        // default mime charset, see 
+        // http://tools.ietf.org/html/draft-ietf-appsawg-mime-default-charset-04
+        std::string lCharset = "ISO-8859-1"; 
+        PARAMETER* lParam = lCurrentBody->parameter;
+        while (lParam) {
+          std::string lAttribute = lParam->attribute;
+          std::transform(lAttribute.begin(), lAttribute.end(), lAttribute.begin(), ::tolower);
+          if (lAttribute.compare("charset") == 0) {
+            lCharset = lParam->value;
+          }
+          lParam = lParam->next;
+        }
+
+        std::string lTransferEncodingDecoded;
+        unsigned short lEncoding = lCurrentBody->encoding;
+        // decode the body according the transfer encoding if it is quoted-printable
+        decodeTextualTransferEncoding(lBodyContent, lContentType, lEncoding, lTransferEncodingDecoded);
+
+        // decode the body according to the charset
+        std::string lCharsetDecoded;
+        toUtf8(lTransferEncodingDecoded, lCharset, lCharsetDecoded);
+
+        createContentNode(lCurrentParent, lCharsetDecoded, lContentType,
+          "utf-8", getEncoding(lEncoding), lContentDisposition,
+          lContentDispositionFilename, lContentDispositionModificationDate,
+          lContentId);
+
+    } else {
+      lMultipartParent = theModule->getItemFactory()->createElementNode(
+        lCurrentParent, lMultipartParentName, lMultipartParentType, false,
+        false, ns_binding);
+
+      createContentTypeAttributes(lMultipartParent, lContentType, "utf-8",
+        getEncoding(lCurrentBody->encoding), lContentDisposition,
+        lContentDispositionFilename, lContentDispositionModificationDate);
+
+      PART* lPart = lCurrentBody->nested.part;
+      lBodies.insert(lBodies.begin(), &lPart->body);
+      lParents.insert(lParents.begin(), lMultipartParent);      
+      lSections.insert(lSections.begin(), lCurrentSection + "1.");
+      for (int j = 1; lPart->next; ++j) {
+        lPart = lPart->next; 
+        std::stringstream lConverter;
+        lConverter << j+1 << "."; 
+        lSections.insert(lSections.begin() + j, lCurrentSection + lConverter.str());
+        lConverter.clear(); 
+        lBodies.insert(lBodies.begin() +j, &lPart->body);
+        lParents.insert(lParents.begin(), lMultipartParent);
+      }
+    } 
+  }
+}
+
+void
+ImapFunction::toUtf8(
+  const std::string& aValue,
+  const std::string& aFromCharset,
+  std::string& aResult) const
+{
+  if (aFromCharset == "") {
+    aResult = aValue;
+    return;
+  }
+
+  // transforming the body from the declared charset to utf-8
+  const char* lValueChar = aValue.c_str();
+  // TODO array auto ptr
+  UChar* lUnicodeBody = new UChar[aValue.length()+1];
+  UErrorCode lStatus = U_ZERO_ERROR;
+  UConverter *lConverter;
+
+  // set up the converter
+  lConverter = ucnv_open(aFromCharset.c_str(), &lStatus);
+  checkStatus(lStatus);
+
+  // convert to Unicode
+  int32_t lUnicodeLen = ucnv_toUChars(
+      lConverter, 
+      lUnicodeBody, 
+      aValue.length()+1, 
+      lValueChar, 
+      -1, 
+      &lStatus);
+  checkStatus(lStatus);
+
+  int32_t lUTF8Memory = lUnicodeLen*4 + 1;
+  // TODO autoptr
+  char* lUTF8Body = new char[lUTF8Memory];
+  int32_t lUTF8Len;
+
+  //convert from unicode to UTF8
+  u_strToUTF8(lUTF8Body, 
+              lUTF8Memory, 
+              &lUTF8Len, 
+              lUnicodeBody, 
+              -1, 
+              &lStatus);
+  checkStatus(lStatus);
+
+  aResult = lUTF8Body;
+}
+
+
+void
+ImapFunction::checkStatus(UErrorCode aStatus) const
+{
+  if (!U_SUCCESS(aStatus)) {
+    std::stringstream lStream;
+    lStream << "Failed to convert email fragment (subject or body) to UTF-8. ICU error code: " << u_errorName(aStatus) << ".";
+    raiseImapError("IMAP0001", lStream.str());
+  }
+}
+
+struct PrintableAsciiChar
+{
+  bool operator()(char c) const {
+    unsigned int u = static_cast<unsigned int>(c);
+    return !(u == '\t' || u == '\n' || u == '\t' || (u >= 32 && u <= 127)); 
+  }
+};
+
+void
+ImapFunction::decodeHeader(
+  const std::string& aValue,
+  std::string& aResult) const
+{
+  std::string lValue = aValue;
+  // We assume that email headers must not contain non-printable characters
+  // because special chars need to be encoded.
+  // Therefore, we filter everything non-printable out to avoid problems.
+  lValue.erase(
+    std::remove_if(
+      lValue.begin(),
+      lValue.end(),
+      PrintableAsciiChar()), 
+    lValue.end()
+  );
+
+  std::stringstream lDecoded;
+  std::size_t lMarker = 0;
+
+  // size used many times
+  std::size_t lLength = lValue.length();
+  // to collect question mark positions
+  std::vector<std::size_t> lQMs;
+
+  // populate the above vectors
+  for (std::size_t i = 0; i < lLength; i++) {
+    if (lValue.at(i) == '?') {
+      lQMs.push_back(i);
+    }
+  }
+
+  // sizes we need below
+  std::size_t lQLength = lQMs.size();
+
+  // not enough questions marks to make up an encoding, give up
+  if (lQLength < 4) {
+    aResult = lValue;
+    return;
+  }
+
+  // now we take groups of 4 question marks
+  for (std::size_t j = 0; j <= lQLength - 4; ) {
+    // a good encoding meets these conditions:
+    if (
+      // 2nd and 3rd question marks have only one character in between
+      lQMs[j + 1] + 2 == lQMs[j + 2] &&
+      // 1st question mark is prefixed by an equal sign
+      (lQMs[j]  > 0 && lValue.at(lQMs[j] - 1) == '=') &&
+      // 4th question mark is suffixes by an equal sign
+      (lQMs[j + 3] < (lLength-1) && lValue.at(lQMs[j + 3] + 1) == '='))
+    {
+      // ok were good, so first save the text from the last marker
+      // upto the starting equal sign
+      lDecoded << lValue.substr(lMarker, lQMs[j] - lMarker - 1);
+
+      // then take the entire region, including =? and ?= and try to decode it
+      std::string lWords;
+      decodeEncodedWords(lValue.substr(lQMs[j] - 1, lQMs[j + 3] - lQMs[j] + 3), lWords);
+      lDecoded << lWords;
+
+      // save the new marker at the end of this encoded word group
+      lMarker = lQMs[j + 3] + 2;
+
+      // decoding with the current 4 question marks worked well so we skip them and try the next 4
+      j += 4;
+    }
+    else {
+      // not a valid encoding, so iterate to the next question mark
+      ++j;
+    }
+  }
+  lDecoded << lValue.substr(lMarker);
+
+  aResult = lDecoded.str();
+}
+
+bool isTextOrXMLContentType(const std::string& aContentType) {
+  return  aContentType.find("text/") != std::string::npos
+       || aContentType == "application/xml"
+       || aContentType.find("+xml") != std::string::npos;
+}
+
+void
+ImapFunction::decodeTextualTransferEncoding(
+  const std::string& aValue, 
+  const std::string& aContentType, 
+  unsigned short& aEncoding, 
+  std::string& aResult) const
+{
+  if (aEncoding == ENCQUOTEDPRINTABLE) {
+    unsigned long lNewLength;
+    void* lNewData = rfc822_qprint((unsigned char*)aValue.c_str(), aValue.length(), &lNewLength);
+    aResult = std::string((char *)lNewData, lNewLength);
+    fs_give(&lNewData);
+    aEncoding = ENC8BIT;
+    if (!isTextOrXMLContentType(aContentType)) {
+      // binary content needs to be base64 encoded for zorba
+      std::string lOutput;
+      zorba::base64::encode(aResult, &lOutput);
+      aResult = lOutput;
+    }
+  }
+  else if (aEncoding == ENCBASE64) {
+    aResult = aValue;
+    // remove newlines from base64 
+    aResult.erase(std::remove(aResult.begin(), aResult.end(), '\r'), aResult.end());
+    aResult.erase(std::remove(aResult.begin(), aResult.end(), '\n'), aResult.end());
+    if (isTextOrXMLContentType(aContentType))
+    {
+      unsigned long lNewLength;
+      void* lNewData = rfc822_base64((unsigned char*)aResult.c_str(), aResult.length(), &lNewLength);
+      aResult = std::string((char *)lNewData, lNewLength);
+      fs_give(&lNewData);
+      aEncoding = ENC8BIT;
+    }
+  }
+  else
+  {
+    aResult = aValue;
+  }
+}
+
+} /* namespace emailmodule */
+} /* namespace zorba */

=== added file 'src/com/zorba-xquery/www/modules/email/imap.xq.src/imap_function.h'
--- src/com/zorba-xquery/www/modules/email/imap.xq.src/imap_function.h	1970-01-01 00:00:00 +0000
+++ src/com/zorba-xquery/www/modules/email/imap.xq.src/imap_function.h	2014-04-30 23:07:12 +0000
@@ -0,0 +1,204 @@
+/*
+ * Copyright 2006-2008 The FLWOR Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ZORBA_EMAILMODULE_IMAPFUNCTION_H
+#define ZORBA_EMAILMODULE_IMAPFUNCTION_H
+
+#include <string>
+
+#include <zorba/function.h>
+#include <zorba/error.h>
+
+#include <unicode/utypes.h>
+
+
+namespace zorba { namespace emailmodule {
+
+class ImapModule;
+class EmailException;
+
+class ImapFunction : public ContextualExternalFunction
+{
+  protected:
+    const ImapModule* theModule;
+    static const char* SCHEMA_NAMESPACE;
+    static const char* SCHEMA_PREFIX;
+
+    void
+    raiseImapError(
+      EmailException& e) const;
+
+    void
+    raiseImapError(
+      const std::string& qName,
+      const std::string& message) const;
+
+    void
+    getHostUserPassword(
+      const ExternalFunction::Arguments_t& aArgs,
+      int aPos,
+      std::string& aHost,
+      std::string& aUserName,
+      std::string& aPassword) const;
+
+    String
+    getOneStringArg(
+      const ExternalFunction::Arguments_t& args,
+      int pos) const;
+
+    std::string
+    getMessageNumbers(
+      const ExternalFunction::Arguments_t& args,
+      int pos) const;
+
+    unsigned long
+    getOneMessageNumber(
+      const ExternalFunction::Arguments_t& args,
+      int pos) const;
+
+    bool
+    getOneBoolArg(
+      const ExternalFunction::Arguments_t& args,
+      int pos) const;
+
+    /*
+      * Converts a dateTime string as returned by the c-client (e.g. Tue, 24
+      * Aug 2010 16:26:10 +0200'DD) into a xs:dateTime format.
+      */
+    std::string
+    getDateTime(const std::string& aCClientDateTime) const;
+
+    std::string
+    getContentType(const unsigned short aType, const char* aSubtype) const;
+
+    std::string
+    getEncoding(const unsigned short aEncoding) const;
+
+    void
+    createFlagsNode(
+      Item& aParent,
+      Item& aFlags,
+      std::vector<int>& aFlagsVector,
+      const bool aQualified) const;
+
+    /*
+      * Creates a simple named  node containing a text node.
+      */
+    void
+    createInnerNodeWithText(
+      Item& aParent,
+      const std::string& aNamespace,
+      const std::string& aPrefix,
+      const std::string& aName,
+      const std::string& aTypeNamespace,
+      const std::string& aType,
+      const std::string& aContent) const;
+
+    void
+    createContentNode(
+      Item& aParent,
+      const std::string& aContent,
+      const std::string& contentType,
+      const std::string& charset,
+      const std::string& contentTransferEncoding,
+      const std::string& aContentDisposition,
+      const std::string& aContentDispositionFilename,
+      const std::string& aContentDispositionModificationDate,
+      const std::string& aContentId) const;
+
+    /*
+      * Creates a simple email address node as defined in email.xsd
+      */
+    void
+    createEmailAddressNode(
+      Item& aParent,
+      const std::string& aName,
+      const char * aPersonal,
+      const char* aMailbox,
+      const char* aHost) const;
+
+    void
+    createRecipientNode(
+      Item& aParent,
+      const std::string& aName,
+      const char* aPersonal,
+      const char* aMailbox,
+      const char* aHost) const;
+
+    void
+    createContentTypeAttributes(
+      Item& aParent,
+      const std::string& aValue,
+      const std::string& aCharset,
+      const std::string& aTransferEncoding,
+      const std::string& aContentDisposition,
+      const std::string& aContentDispositionFilename,
+      const std::string& aContentDispositionModificationDate) const;
+
+    void
+    getMessage(
+      Item& aParent,
+      const std::string& aHostName,
+      const std::string& aUserName,
+      const std::string& aPassword,
+      const std::string& aMailbox,
+      const unsigned long aMessageNumber,
+      const bool aUid,
+      const  bool aOnlyEnvelope) const;
+
+    void
+    decodeTextualTransferEncoding(const std::string& aValue,
+      const std::string& aContentType,
+      unsigned short& aEncoding,
+      std::string& aResult) const;
+
+    void
+    toUtf8(
+      const std::string& value,
+      const std::string& fromCharset,
+      std::string& result) const;
+
+    void
+    checkStatus(UErrorCode aStatus) const;
+
+    /**
+     * Decodes header of an email, e.g. the subject.
+     */
+    void
+    decodeHeader(
+      const std::string& value,
+      std::string& result) const;
+
+    // This function is defined in imap.cpp because if defined in imap_function.cpp
+    // some header file conflict are raised and it does not compile
+    void
+    decodeEncodedWords(
+      const std::string& value,
+      std::string& result) const;
+
+  public:
+    ImapFunction(const ImapModule* module);
+    ~ImapFunction();
+
+    virtual String
+    getURI() const;
+
+};
+
+} /* namespace emailmodule */
+} /* namespace zorba */
+
+#endif /* ZORBA_EMAILMODULE_IMAPFUNCTION_H */

=== added file 'src/com/zorba-xquery/www/modules/email/imap.xq.src/imap_module.cpp'
--- src/com/zorba-xquery/www/modules/email/imap.xq.src/imap_module.cpp	1970-01-01 00:00:00 +0000
+++ src/com/zorba-xquery/www/modules/email/imap.xq.src/imap_module.cpp	2014-04-30 23:07:12 +0000
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2006-2008 The FLWOR Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "imap.h"
+#include "imap_module.h"
+#include "imap_function.h"
+
+namespace zorba { namespace emailmodule {
+
+  ItemFactory* ImapModule::theFactory = 0;
+
+
+ImapModule::~ImapModule()
+{
+  for (FuncMap_t::const_iterator lIter = theFunctions.begin();
+       lIter != theFunctions.end(); ++lIter) {
+    delete lIter->second;
+  }
+  theFunctions.clear();
+}
+  
+ExternalFunction*
+ImapModule::getExternalFunction(const String& aLocalname)
+{
+  ExternalFunction*& lFunc = theFunctions[aLocalname];
+  if (!lFunc) {
+    if (1 == 0) {
+    } else if (aLocalname == "status-impl") {
+      lFunc = new StatusFunction(this);
+    } else if (aLocalname == "create-impl") {
+      lFunc = new CreateFunction(this);
+    } else if (aLocalname == "delete-impl") {
+      lFunc = new DeleteFunction(this);
+    } else if (aLocalname == "rename-impl") {
+      lFunc = new RenameFunction(this);
+    } else if (aLocalname == "list-impl") {
+      lFunc = new ListFunction(this);
+    } else if (aLocalname == "subscribe-impl") {
+      lFunc = new SubscribeFunction(this);
+    } else if (aLocalname == "unsubscribe-impl") {
+      lFunc = new UnsubscribeFunction(this);
+    } else if (aLocalname == "expunge-impl") {
+      lFunc = new ExpungeFunction(this);
+    } else if (aLocalname == "search-impl") {
+      lFunc = new SearchFunction(this);
+    } else if (aLocalname == "copy-impl") {
+      lFunc = new CopyFunction(this);
+    } else if (aLocalname == "fetch-envelope-impl") {
+      lFunc = new FetchEnvelopeFunction(this);
+    } else if (aLocalname == "fetch-message-impl") {
+      lFunc = new FetchMessageFunction(this);
+    } else if (aLocalname == "fetch-subject-impl") {
+      lFunc = new FetchSubjectFunction(this);
+    } else if (aLocalname == "fetch-from-impl") {
+      lFunc = new FetchFromFunction(this);
+    } else if (aLocalname == "fetch-uid-impl") {
+      lFunc = new FetchUidFunction(this);
+    } else if (aLocalname == "fetch-message-sequence-number-impl") {
+      lFunc = new FetchMessageSequenceNumberFunction(this);
+    } else if (aLocalname == "fetch-flags-impl") {
+      lFunc = new FetchFlagsFunction(this);
+    } else if (aLocalname == "set-flags-impl") {
+      lFunc = new SetFlagsFunction(this);
+    }  
+  }
+  return lFunc;
+}
+
+void
+ImapModule::destroy()
+{
+  if (!dynamic_cast<ImapModule*>(this)) {
+    return;
+  }
+  delete this;
+}
+
+} /* namespace emailmodule */ } /* namespace zorba */

=== added file 'src/com/zorba-xquery/www/modules/email/imap.xq.src/imap_module.h'
--- src/com/zorba-xquery/www/modules/email/imap.xq.src/imap_module.h	1970-01-01 00:00:00 +0000
+++ src/com/zorba-xquery/www/modules/email/imap.xq.src/imap_module.h	2014-04-30 23:07:12 +0000
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2006-2008 The FLWOR Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ZORBA_EMAILMODULE_IMAPMODULE_H
+#define ZORBA_EMAILMODULE_IMAPMODULE_H
+
+#include <map>
+
+#include <zorba/zorba.h>
+#include <zorba/external_module.h>
+
+namespace zorba { namespace emailmodule {
+
+class ImapModule : public ExternalModule
+{
+  private:
+    static ItemFactory* theFactory;
+
+  protected:
+    class ltstr
+    {
+      public:
+        bool operator()(const String& s1, const String& s2) const
+        {
+          return s1.compare(s2) < 0;
+        }
+    };
+  
+    typedef std::map<String, ExternalFunction*, ltstr> FuncMap_t;
+
+    FuncMap_t theFunctions;
+  
+  public:
+    virtual ~ImapModule();
+  
+    virtual String
+    getURI() const { return ImapModule::getURIString(); }
+  
+    virtual ExternalFunction*
+    getExternalFunction(const String& aLocalname);
+
+    virtual void
+    destroy();
+
+    static ItemFactory*
+    getItemFactory()
+    {
+      if(!theFactory)
+      {
+        theFactory = Zorba::getInstance(0)->getItemFactory();
+      }
+    
+      return theFactory;
+    }
+  
+    static String
+    getURIString() {
+      static String lURI = "http://www.zorba-xquery.com/modules/email/imap";;
+      return lURI;
+    }
+};
+
+
+} /* namespace emailmodule */ 
+} /* namespace zorba */
+
+#endif /* ZORBA_EMAILMODULE_IMAPMODULE_H */

=== added file 'src/com/zorba-xquery/www/modules/email/smtp.xq'
--- src/com/zorba-xquery/www/modules/email/smtp.xq	1970-01-01 00:00:00 +0000
+++ src/com/zorba-xquery/www/modules/email/smtp.xq	2014-04-30 23:07:12 +0000
@@ -0,0 +1,97 @@
+xquery version "3.0";
+
+(:
+ : Copyright 2006-2009 The FLWOR Foundation.
+ :
+ : Licensed under the Apache License, Version 2.0 (the "License");
+ : you may not use this file except in compliance with the License.
+ : You may obtain a copy of the License at
+ :
+ : http://www.apache.org/licenses/LICENSE-2.0
+ :
+ : Unless required by applicable law or agreed to in writing, software
+ : distributed under the License is distributed on an "AS IS" BASIS,
+ : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ : See the License for the specific language governing permissions and
+ : limitations under the License.
+:)
+
+(:~
+ : This module can be used for sending emails.
+ :
+ : The SMTP module contains only one public function that receives two parameters.
+ : The SMTP server access information passed as an <code>hostInfo</code> element
+ : and the email message representation as a <code>message</code> element.
+ : For a quick start see the examples associates with the <code>send(...)</code>
+ : function. For a complete specification read, the description and the
+ : documentation associated with this function.
+ :
+ : @author Sorin Nasoi, Daniel Thomas
+ : @see <a href="http://www.washington.edu/imap/";>c-client Library part of UW IMAP toolkit</a>
+ : @library <a href="http://www.washington.edu/imap/";>c-client Library part of UW IMAP toolkit</a>
+ : @project Zorba/Input Output/SMTP
+ :)
+module namespace smtp = "http://www.zorba-xquery.com/modules/email/smtp";;
+
+import schema namespace email = 'http://www.zorba-xquery.com/modules/email';
+
+declare namespace an = "http://zorba.io/annotations";;
+
+declare namespace ver = "http://zorba.io/options/versioning";;
+declare option ver:module-version "1.0";
+
+(:~
+ : This function sends an email message from the specified account.
+ :
+ : The <code>hostName</code> child element of <code>$host-info</code> must have the form:
+ : <code><b>remote_system_name</b> [":" <b>port</b>] [<b>flags</b>]</code>. This syntax is part of the
+ : <a href="http://www.washington.edu/imap/documentation/naming.txt.html"; target="_blank">Remote names</a>
+ : syntax defined in the UW IMAP toolkit. The <code><b>remote_system_name</b></code> and
+ : <code><b>flags</b></code> fragments are explained in the section <code>III</code> of this document.
+ :
+ : For example the hostName could look like:
+ : <ul>
+ :   <li><code>&lt;hostName&gt;smtp.gmail.com:587/tls/novalidate-cert&lt;hostName&gt;</code></li>
+ :   <li><code>&lt;hostName&gt;[209.85.129.111]:587/tls/novalidate-cert&lt;hostName&gt;</code></li>
+ : </ul>
+ :
+ : The <code>$host-info</code> parameter could then look like this:
+ : <pre class="ace-static" ace-mode="xquery"><![CDATA[
+ : <hostInfo>
+ :   <hostName>smtp.gmail.com:587/tls/novalidate-cert</hostName>
+ :   <userName>username</userName>
+ :   <password>password</password>
+ : </hostInfo>
+ : ]]></pre>
+ :
+ : For a complete of the structure of an email message, see the imported email
+ : schema: <code>http://www.zorba-xquery.com/modules/email</code>
+ :
+ : All the data passed to this function does not need to be validated.
+ : The only requirement is that they have a valid format and are in the
+ : correct namespace according to the schema:
+ : <code>http://www.zorba-xquery.com/modules/email</code>.
+ : 
+ : @param $host-info The SMTP host, user name, and password.
+ : @param $message The message to send as defined in the email XML schema.
+ : @return The function is declared as sequential and has side-effects. It returns the empty sequence.
+ : @error smtp:SMTP0001 The message format is invalid.
+ : @error smtp:SMTP0002 The message has no recipient.
+ : @error smtp:SMTP0003 The message could not be sent.
+ : @error smtp:SMTP9999 If any other error occurs.
+ : @error err:XQDY0027 If the values of the arguments are not not valid
+ :    according to the email schema:
+ :    <code>http://www.zorba-xquery.com/modules/email</code>
+ : @example examples/Queries/smtp/simple_text.xq
+ : @example examples/Queries/smtp/text_with_image.xq
+ : @example examples/Queries/smtp/html.xq
+ :)
+declare %an:sequential function smtp:send(
+    $host-info as element(email:hostInfo),
+    $message as element(email:message))
+  as empty-sequence()
+{
+  smtp:send-impl(validate{$host-info}, validate{$message})
+}; 
+
+declare %private %an:sequential function smtp:send-impl($host-info as element(email:hostInfo), $message as element(email:message)) as empty-sequence() external;

=== added directory 'src/com/zorba-xquery/www/modules/email/smtp.xq.src'
=== added file 'src/com/zorba-xquery/www/modules/email/smtp.xq.src/mime_handler.cpp'
--- src/com/zorba-xquery/www/modules/email/smtp.xq.src/mime_handler.cpp	1970-01-01 00:00:00 +0000
+++ src/com/zorba-xquery/www/modules/email/smtp.xq.src/mime_handler.cpp	2014-04-30 23:07:12 +0000
@@ -0,0 +1,647 @@
+/*
+ * Copyright 2006-2008 The FLWOR Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cstdio>
+#include <sstream>
+#include <vector>
+
+#include <zorba/item_factory.h>
+#include <zorba/iterator.h>
+#include <zorba/store_consts.h>
+#include <zorba/user_exception.h>
+#include <zorba/util/base64_util.h>
+#include <zorba/xquery_functions.h>
+#include <zorba/zorba_string.h>
+
+#include "mime_handler.h"
+#include "email_exception.h"
+
+namespace zorba { namespace emailmodule {
+
+// helper function for retrieving the NodeName of an Item
+static void
+getNodeName(const Item aElement, zorba::String& aValue)
+{
+  Item lNodeName;
+  aElement.getNodeName(lNodeName);
+  aValue = lNodeName.getLocalName();
+}
+
+// helper function for retrieving the string value of a Text Node
+static void
+getTextValue(const Item aElement, zorba::String& aValue)
+{
+  Iterator_t lChildrenIt;
+  Item       lChild;
+
+  aValue = String();
+  lChildrenIt = aElement.getChildren();
+  lChildrenIt->open();
+  while (lChildrenIt->next(lChild)) {
+    if (lChild.getNodeKind() == store::StoreConsts::textNode) {
+      aValue.append(lChild.getStringValue());
+    }
+  }
+
+  lChildrenIt->close();
+}
+
+/**
+ * Encodes a zorba String if necessary (if it contains non-ascii chars)
+ * and assigns it to the passed char-pointer-reference.
+ */
+void encodeStringForEMailHeader(const zorba::String& aString, char*& aCClientVal)
+{
+  // check if string contains non ascii chars
+  bool lContainsNonAscii = false;
+  for (
+    zorba::String::const_iterator lIter = aString.begin();
+    lIter != aString.end();
+    ++lIter)
+  {
+    unsigned int u = static_cast<unsigned int>(*lIter);
+    if (!(u == '\t' || u == '\n' || u == '\t' || (u >= 32 && u <= 127)))
+    {
+      lContainsNonAscii = true;
+      break;
+    }
+  }
+
+  if (lContainsNonAscii)
+  {
+    // if string contains non-ascii chars, we encode it with
+    // base64 encoding and generate a header value according to
+    // http://tools.ietf.org/html/rfc2047 (MIME encoded-word syntax).
+    zorba::String lEncodedValue;
+    zorba::base64::encode(aString, &lEncodedValue);
+    zorba::String lFullValue = zorba::String("=?UTF-8?B?") 
+                             + lEncodedValue 
+                             + zorba::String("?=");
+    aCClientVal = cpystr(lFullValue.c_str());
+  }
+  else 
+  {
+    // if string contains ascii chars only, do don't encode anything
+    aCClientVal = cpystr(aString.c_str());
+  }
+}
+
+// helper function for retrieving the name and email address from an item
+static void
+getNameAndEmailAddress(
+  Item& aEmailItem,
+  String& aName,
+  String& aMailbox,
+  String& aHost)
+{
+  Iterator_t lChildren = aEmailItem.getChildren();
+  lChildren->open();
+  Item lChild;
+  // name might not exist -> empty string by default
+  aName = "";
+  while (lChildren->next(lChild)) {
+    if (lChild.getNodeKind() != store::StoreConsts::elementNode) {
+      continue;
+    }
+
+    String lNodeName;
+    getNodeName(lChild, lNodeName);
+    if (lNodeName == "name") {
+      aName = lChild.getStringValue();
+    } else {
+      String lEmail = lChild.getStringValue();
+      int lIndexOfAt = lEmail.find('@'); 
+      aMailbox = lEmail.substr(0, lIndexOfAt).c_str();
+      aHost = lEmail.substr(lIndexOfAt + 1, lEmail.length() - lIndexOfAt - 1).c_str();
+    }  
+  }
+}
+
+mail_address*
+create_mail_address(String& aName, String& aMailbox, String& aHost)
+{
+  mail_address* address = mail_newaddr();
+  encodeStringForEMailHeader(aName, address->personal);
+  encodeStringForEMailHeader(aMailbox, address->mailbox);
+  encodeStringForEMailHeader(aHost, address->host);
+  return address;
+}
+
+
+CClientMimeHandler::~CClientMimeHandler()
+{
+}
+
+void
+CClientMimeHandler::begin(const Item& aMimeItem)
+{
+  Iterator_t lChildIter;
+
+  //initialize ENVELOPE
+  theEnvelope = mail_newenvelope ();
+  
+  //initialize BODY
+  theBody = mail_newbody ();
+  mail_initbody(theBody);
+
+  //set theMessageItem
+  lChildIter = aMimeItem.getChildren();
+  lChildIter->open();
+
+  // read envelope and body elements but skip non-element nodes
+  while (lChildIter->next(theEnvelopeItem)) {
+    if (theEnvelopeItem.getNodeKind() == store::StoreConsts::elementNode) {
+      break;
+    }
+  }
+  while (lChildIter->next(theBodyItem)) {
+    if (theBodyItem.getNodeKind() == store::StoreConsts::elementNode) {
+      break;
+    }
+  }
+
+  lChildIter->close();
+}
+
+void
+CClientMimeHandler::end()
+{
+}
+
+void
+CClientMimeHandler::envelope()
+{
+  if (theEnvelopeItem.isNull()) {
+    throw EmailException("PARSE_ERROR", "The message could not be parsed.");
+  }
+
+  //set the date from the client.
+  //If this is not set it defaults to the date of the SMTP server.
+  char line[MAILTMPLEN];
+  rfc822_date (line);
+  theEnvelope->date = (unsigned char *) fs_get (1+strlen (line));
+  strcpy((char *)theEnvelope->date,line);
+
+
+  Iterator_t    lChildIter;
+  zorba::Item   lChild;
+  String lNodeName, lNodeValue;
+  String lName, lMailbox, lHost;
+
+  lChildIter = theEnvelopeItem.getChildren();
+  lChildIter->open();
+  while (lChildIter->next(lChild)) {
+    if (lChild.getNodeKind() != store::StoreConsts::elementNode) {
+      continue;
+    }
+
+    getNodeName(lChild, lNodeName);
+    getTextValue(lChild, lNodeValue);
+
+    if (lNodeName == "date") {
+      char lDate[MAILTMPLEN]; 
+      parseXmlDateTime(lNodeValue, lDate);
+      theEnvelope->date = (unsigned char *) fs_get (1+strlen (lDate));
+      strcpy ((char *)theEnvelope->date, lDate);
+    } else if (lNodeName == "from") {
+      getNameAndEmailAddress(lChild, lName, lMailbox, lHost);
+      theEnvelope->from = create_mail_address(lName, lMailbox, lHost);
+    } else if (lNodeName == "sender") {
+      getNameAndEmailAddress(lChild, lName, lMailbox, lHost);
+      theEnvelope->sender = create_mail_address(lName, lMailbox, lHost);
+    } else if (lNodeName == "replyto") {
+      getNameAndEmailAddress(lChild, lName, lMailbox, lHost);
+      theEnvelope->reply_to = create_mail_address(lName, lMailbox, lHost);
+    } else if (lNodeName == "subject") {
+      encodeStringForEMailHeader(lNodeValue, theEnvelope->subject);
+    } else if (lNodeName == "recipient") {
+      Iterator_t lRecipentChildren = lChild.getChildren(); 
+      lRecipentChildren->open();
+      Item lRecipentChild;
+      // read the recipient element but skip comments
+      while (lRecipentChildren->next(lRecipentChild)) {
+        if (lRecipentChild.getNodeKind() == store::StoreConsts::elementNode) {
+          break;
+        }
+      }
+      getNodeName(lRecipentChild, lNodeName);
+      lRecipentChildren->close();
+
+      if (lNodeName == "to") {
+        getNameAndEmailAddress(lRecipentChild, lName, lMailbox, lHost);
+        // there can be multiple to nodes, iterate to the next free one!
+        ADDRESS** lNext = &theEnvelope->to;
+        while (*lNext) {
+          lNext = &((*lNext)->next);
+        }  
+        *lNext = create_mail_address(lName, lMailbox, lHost);
+      } else if(lNodeName == "cc") {
+        getNameAndEmailAddress(lRecipentChild, lName, lMailbox, lHost);
+        ADDRESS** lNext = &theEnvelope->cc;
+        while (*lNext) {
+          lNext = &((*lNext)->next);
+        }  
+        *lNext = create_mail_address(lName, lMailbox, lHost);
+      } else if (lNodeName == "bcc") {
+        getNameAndEmailAddress(lRecipentChild, lName, lMailbox, lHost);
+        ADDRESS** lNext = &theEnvelope->bcc;
+        while (*lNext) {
+          lNext = &((*lNext)->next);
+        }  
+        *lNext = create_mail_address(lName, lMailbox, lHost);
+      }
+    }       
+  }
+  lChildIter->close();
+}
+
+void
+CClientMimeHandler::body()
+{
+  theBody->type = TYPEOTHER;
+
+  Iterator_t lChildIter;
+  Item lChild;
+  String lNodeName;
+
+  lChildIter = theBodyItem.getChildren();
+  lChildIter->open();
+  while (lChildIter->next(lChild)) {
+    if (lChild.getNodeKind() != store::StoreConsts::elementNode) {
+      continue;
+    }
+
+    getNodeName(lChild, lNodeName);
+
+    if (lNodeName == "content") {
+      parse_content(theBody, lChild);
+    }
+    else if (lNodeName == "multipart") {
+      parse_multipart(theBody, lChild);
+    }
+  }
+  lChildIter->close();
+}
+
+void
+CClientMimeHandler::set_text_body(BODY* aBody, String& aMessage)
+{
+  String lMessage;
+  // special case for encoding of base64 which needs a new line after 64 characters
+  if (aBody->encoding == ENCBASE64) {
+    std::stringstream lInStream;
+    std::stringstream lOutStream;
+    // for loop that counts to 64 and then makes a new line
+    lInStream << aMessage.c_str();
+    char next;
+    int counter = 0;
+    while (lInStream >> next) {
+      if (++counter == 64) {
+        lOutStream << "\r\n";
+        counter = 1;
+      }
+      lOutStream << next;
+    }  
+    lMessage = lOutStream.str(); 
+  } else {
+    lMessage = aMessage;
+  }
+    
+  char *text = (char *) fs_get (strlen(lMessage.c_str()));
+  text = cpystr (lMessage.c_str());
+  aBody->contents.text.size = strlen(text);
+  aBody->contents.text.data = (unsigned char *) text;   //message body
+
+}
+
+PARAMETER*
+CClientMimeHandler::create_param(
+  String aAttribute,
+  String aValue,
+  PARAMETER* aPrevious)
+{
+  PARAMETER *lParam;
+  lParam = mail_newbody_parameter();
+  lParam->attribute = cpystr (aAttribute.c_str());
+  lParam->value = cpystr (aValue.c_str());
+
+  if (aPrevious) {
+    aPrevious->next = lParam;
+  }
+
+  return lParam;
+}
+
+void
+CClientMimeHandler::set_encoding(BODY* aBody, String& aEncoding)
+{
+  String lUpperEnc = fn::upper_case(aEncoding);
+
+  if (lUpperEnc == "ENC7BIT")
+    aBody->encoding = ENC7BIT;
+  else if (lUpperEnc == "ENC8BIT")
+    aBody->encoding = ENC8BIT;
+  else if (lUpperEnc == "ENCBINARY")
+    aBody->encoding = ENCBINARY;
+  else if (lUpperEnc == "ENCBASE64")
+    aBody->encoding = ENCBASE64;
+  else if (lUpperEnc == "ENCQUOTEDPRINTABLE")
+    aBody->encoding = ENCQUOTEDPRINTABLE;
+  else
+    aBody->encoding = ENCOTHER;
+}
+
+bool
+CClientMimeHandler::set_content_type_value(BODY* aBody, String& aValue)
+{
+  bool lRes = true;
+  int lPos = aValue.find('/');
+  String lLowerType = fn::lower_case(aValue.substr(0, lPos));
+
+  //set the BODY content type
+  if (lLowerType == "text")
+    aBody->type = TYPETEXT;
+  else if (lLowerType == "multipart")
+    aBody->type = TYPEMULTIPART;
+  else if (lLowerType == "message")
+    aBody->type = TYPEMESSAGE;
+  else if (lLowerType == "application")
+    aBody->type = TYPEAPPLICATION;
+  else if (lLowerType == "image")
+    aBody->type = TYPEIMAGE;
+  else if (lLowerType == "audio")
+    aBody->type = TYPEAUDIO;
+  else if (lLowerType == "video")
+    aBody->type = TYPEVIDEO;
+  else {
+    aBody->type = TYPEOTHER;
+    lRes = false;
+  }
+
+  //set the BODY content subtype
+  if (lRes) {
+    // the list of subtypes of each type is available at
+    // http://www.iana.org/assignments/media-types/
+    String lSubtype = aValue.substr(lPos + 1, aValue.length() - lPos);
+    aBody->subtype = cpystr(fn::upper_case(lSubtype).c_str());
+  }
+
+  return lRes;
+}
+
+void
+CClientMimeHandler::set_contentTypeCharsetCTF(
+  BODY* aBody,
+  const Item& aContentOrMultipartItem)
+{     
+  Iterator_t lAttributes = aContentOrMultipartItem.getAttributes();
+  lAttributes->open();
+  Item lAttributeItem;
+  String lNodeName, lNodeValue;
+  while (lAttributes->next(lAttributeItem)) {
+    getNodeName(lAttributeItem, lNodeName); 
+    lNodeValue = lAttributeItem.getStringValue();
+
+    if (lNodeName == "contentType") {
+      set_content_type_value(aBody, lNodeValue);
+    } else if (lNodeName == "charset") {
+      aBody->parameter = create_param("charset", fn::upper_case(lNodeValue), NIL);
+    } else if (lNodeName == "contentTransferEncoding") {
+      set_encoding(aBody, lNodeValue);  
+    } else if (lNodeName == "contentDisposition") {
+      aBody->disposition.type = cpystr(fn::upper_case(lNodeValue).c_str()); 
+    } else if (lNodeName == "contentDisposition-filename") {
+      if (!aBody->disposition.parameter) {  
+        aBody->disposition.parameter = create_param("filename", lNodeValue, NIL);
+      } else {
+        aBody->disposition.parameter->next = create_param("filename", lNodeValue, NIL);
+      }
+    } else if (lNodeName == "contentDisposition-modification-date") {
+      char lDate[MAILTMPLEN];
+      parseXmlDateTime(lNodeValue, lDate);      
+      if (!aBody->disposition.parameter) {
+        aBody->disposition.parameter = create_param("modification-date", lDate); 
+      } else {
+        aBody->disposition.parameter->next = create_param("modification-date", lDate);
+      } 
+    }
+  }
+      
+  lAttributes->close();
+}
+
+
+bool
+CClientMimeHandler::parse_content(BODY* aBody, const Item aItemContent)
+{
+  zorba::String lValue;
+
+  // set the contentType, charset and contentTransferEncoding (which are attributes of a content node)
+  set_contentTypeCharsetCTF(aBody, aItemContent);
+    
+  lValue = aItemContent.getStringValue();
+  set_text_body(aBody, lValue);
+        
+  return true;
+}
+
+bool
+CClientMimeHandler::parse_multipart(BODY* aBody, const Item aItemMultipart)
+{
+  Iterator_t lChildIter;
+  Item lChild;
+  String lNodeName, lNodeValue;
+  PART* lPartRoot = NIL;
+  PART* lPartPrev = NIL;
+ 
+  set_contentTypeCharsetCTF(aBody, aItemMultipart);
+    
+  // a multipart node constists of several content or multipart nodes
+  lChildIter = aItemMultipart.getChildren();
+  lChildIter->open();
+  while (lChildIter->next(lChild)) {
+    if (lChild.getNodeKind() != store::StoreConsts::elementNode) {
+      continue;
+    }
+
+    // a simple content item
+    getNodeName(lChild, lNodeName);
+
+    if (lNodeName == "content") {
+      PART* lPart;
+      lPart = mail_newbody_part();
+      parse_content(&lPart->body, lChild);
+      if (lPartPrev) {
+        lPartPrev->next = lPart;
+      } else {
+        lPartRoot = lPart;
+      }  
+      lPartPrev = lPart;
+    }
+    // a multipart item ... this calls for recursion 
+    else if (lNodeName == "multipart") {
+      PART* lPart;
+      lPart = NIL;
+      lPart = mail_newbody_part();
+
+      parse_multipart(&lPart->body,lChild);
+        
+      if (lPartPrev) {
+        lPartPrev->next = lPart;
+      } else {
+        lPartRoot = lPart;
+      }  
+      lPartPrev = lPart;
+    }
+  }
+  lChildIter->close();
+
+  if (lPartRoot) {
+    aBody->nested.part = lPartRoot;
+  }
+
+  return true;
+}
+
+void 
+CClientMimeHandler::parseXmlDateTime(String& aXmlDateTime, char* aCDateTime)
+{
+    // first we get year, month, day, hour, minute and seconds as zorba strings      
+
+  int lTempIndex;
+  lTempIndex = aXmlDateTime.find('-');
+  String lYearString = aXmlDateTime.substr(0, lTempIndex);
+  aXmlDateTime = aXmlDateTime.substr(lTempIndex+1);
+  
+  lTempIndex = aXmlDateTime.find('-');
+    
+  String lMonthString = aXmlDateTime.substr(0, lTempIndex);
+  aXmlDateTime = aXmlDateTime.substr(lTempIndex+1);
+      
+  lTempIndex = aXmlDateTime.find('T');
+
+  String lDayString = aXmlDateTime.substr(0, lTempIndex);
+  aXmlDateTime = aXmlDateTime.substr(lTempIndex+1);
+            
+  lTempIndex = aXmlDateTime.find(':');
+      
+  String lHourString = aXmlDateTime.substr(0, lTempIndex);
+  aXmlDateTime = aXmlDateTime.substr(lTempIndex+1);
+      
+  lTempIndex = aXmlDateTime.find(':');
+      
+  String lMinutesString = aXmlDateTime.substr(0, lTempIndex);
+  aXmlDateTime = aXmlDateTime.substr(lTempIndex+1);
+     
+  // the next two digits specify the seconds
+  String lSecondsString = aXmlDateTime.substr(0, 2);
+
+
+  MESSAGECACHE * lDummyCache = mail_new_cache_elt (0);
+  unsigned int lTempDatePart;
+     
+
+  // now, according to the specification of the dateTime xml type, we can have either: nothing, a Z (for UTC), -XXXX or +XXXX)
+  String lUTCString = aXmlDateTime.substr(2);
+
+  if (fn::starts_with(lUTCString,"+") || fn::starts_with(lUTCString,"-")) {
+    lTempIndex = lUTCString.find(':');
+    String lUTCHours = lUTCString.substr(1, lTempIndex-1);
+    String lUTCMinutes = lUTCString.substr(lTempIndex + 1);
+        
+    std::stringstream lHoursConverter;
+    lHoursConverter << lUTCHours.c_str();
+    lHoursConverter >> lTempDatePart;
+    lDummyCache->zhours  = lTempDatePart;
+         
+    std::stringstream lMinutesConverter;
+    lMinutesConverter << lUTCMinutes.c_str();
+    lMinutesConverter >> lTempDatePart;
+    lDummyCache->zminutes = lTempDatePart;
+       
+    if (fn::starts_with(lUTCString,"-")) { 
+      lDummyCache->zoccident = 1;
+    }
+  }      
+ 
+  // now we convert them and throw them into a dummy message cache
+  {
+    std::stringstream lConverter;
+    lConverter << lYearString.c_str();
+    lConverter >> lTempDatePart;      
+    lTempDatePart -= 1970;
+    lDummyCache->year = lTempDatePart;
+  }
+
+  {
+    std::stringstream lConverter;
+    lConverter << lMonthString.c_str();
+    lConverter >> lTempDatePart;
+    lDummyCache->month = lTempDatePart;
+  }
+
+  {
+    std::stringstream lConverter;
+    lConverter << lDayString.c_str();
+    lConverter >> lTempDatePart;
+    lDummyCache->day = lTempDatePart;
+  }
+      
+  {
+    std::stringstream lConverter;
+    lConverter << lHourString.c_str();
+    lConverter >> lTempDatePart;
+    lDummyCache->hours = lTempDatePart;
+  }
+
+  {
+    std::stringstream lConverter;
+    lConverter << lMinutesString.c_str();
+    lConverter >> lTempDatePart;
+    lDummyCache->minutes = lTempDatePart;
+  }
+      
+  {
+    std::stringstream lConverter;
+    lConverter << lSecondsString.c_str();
+    lConverter >> lTempDatePart;
+    lDummyCache->seconds = lTempDatePart;
+  }
+          
+  mail_cdate(aCDateTime, lDummyCache); 
+  
+  // like this, we have a string of the form: Sun Aug  8 08:40:40 2010 +0000\n
+  // what we actually would like is follwing: Fri, 10 Dec 2010 14:14:28 +0100 (CET)
+
+  std::stringstream lDate(aCDateTime);
+      
+  std::string lDayAsWord;
+  std::string lMonthAsWord;
+  std::string lDay;
+  std::string lTime;
+  std::string lYear;
+  std::string lUTC;
+
+  lDate >> lDayAsWord >> lMonthAsWord >> lDay >> lTime >> lYear >> lUTC;
+      
+  lDate.str(std::string());
+  lDate << lDayAsWord << ", " << lDay << " " <<  lMonthAsWord << " " << lYear << " " << lTime << " " << lUTC << " (UTF)";  
+    
+  strcpy(aCDateTime, lDate.str().c_str());
+}
+
+} //namespace emailmodule
+} //namespace zorba

=== added file 'src/com/zorba-xquery/www/modules/email/smtp.xq.src/mime_handler.h'
--- src/com/zorba-xquery/www/modules/email/smtp.xq.src/mime_handler.h	1970-01-01 00:00:00 +0000
+++ src/com/zorba-xquery/www/modules/email/smtp.xq.src/mime_handler.h	2014-04-30 23:07:12 +0000
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2006-2008 The FLWOR Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ZORBA_EMAILMODULE_MIMEHANDLER_H
+#define ZORBA_EMAILMODULE_MIMEHANDLER_H
+
+#include <istream>
+
+#include <zorba/item.h>
+
+#include "zorba/api_shared_types.h"
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include "c-client.h"
+
+namespace zorba { namespace emailmodule {
+
+class MimeHandler
+{
+  public:
+    virtual void begin(const Item& mimeItem) = 0;
+    virtual void envelope() = 0;
+    virtual void body() = 0;
+    virtual void end() = 0;
+};
+
+class CClientMimeHandler : public MimeHandler
+{
+  private:
+    // BODY and ENVELOPE structures are described in
+    // http://www.washington.edu/imap/documentation/internal.txt.html
+    BODY*         theBody;
+    ENVELOPE*     theEnvelope;
+    zorba::Item   theEnvelopeItem;
+    zorba::Item   theBodyItem;
+
+    // assign a certain message string to the given BODY
+    //TODO implement a streaming mechanism for large attachments
+    void
+    set_text_body(BODY* aBody,
+                  String& aMessage);
+
+    // set the encoding to the given BODY
+    void
+    set_encoding(BODY* aBody,
+                  zorba::String& aEncoding);
+
+    // set the content Type and content Subtype of the given BODY
+    bool
+    set_content_type_value(BODY* aBody,
+                            zorba::String& aValue);
+
+    // helper function
+    PARAMETER *
+    create_param(
+      String aAttribute,
+      String aValue,
+      PARAMETER * aPrevious = NIL);
+
+    // parse non multipart message
+    bool
+    parse_content(BODY* aBody,
+                  const Item aItemContent);
+
+    // parse multipart message
+    bool
+    parse_multipart(BODY* aBody,
+                    const Item aItemMultipart);
+
+    // set contentType, charset and TranferEncoding
+    void
+    set_contentTypeCharsetCTF(BODY* aBody,
+                              const Item& aContentOrMultipartItem);
+
+
+    // parse a xml dateTime string to something cclient will like
+    void 
+    parseXmlDateTime(String& aXmlDateTime, char* aCDateTime);
+
+  public:
+    void begin(const Item& mimeItem);
+    void envelope();
+    void body();
+    void end();
+
+    BODY*     getBody()     {  return theBody; };
+    ENVELOPE* getEnvelope() {  return theEnvelope; };
+
+    // destroy theBody and theEnvelope
+    ~CClientMimeHandler();
+};
+
+} //namespace email
+} //namespace zorba
+
+#endif // ZORBA_EMAILMODULE_MIMEHANDLER_H

=== added file 'src/com/zorba-xquery/www/modules/email/smtp.xq.src/mime_parser.cpp'
--- src/com/zorba-xquery/www/modules/email/smtp.xq.src/mime_parser.cpp	1970-01-01 00:00:00 +0000
+++ src/com/zorba-xquery/www/modules/email/smtp.xq.src/mime_parser.cpp	2014-04-30 23:07:12 +0000
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2006-2008 The FLWOR Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mime_parser.h"
+
+namespace zorba { namespace emailmodule {
+
+void
+MimeParser::parse(const Item& aMimeItem, std::stringstream& aDiagnostics)
+{
+  theHandler->begin(aMimeItem);
+
+  theHandler->envelope();
+  theHandler->body();
+
+  theHandler->end();
+}
+
+} // namespace emailmodule
+} // namespace zorba

=== added file 'src/com/zorba-xquery/www/modules/email/smtp.xq.src/mime_parser.h'
--- src/com/zorba-xquery/www/modules/email/smtp.xq.src/mime_parser.h	1970-01-01 00:00:00 +0000
+++ src/com/zorba-xquery/www/modules/email/smtp.xq.src/mime_parser.h	2014-04-30 23:07:12 +0000
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2006-2008 The FLWOR Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ZORBA_EMAILMODULE_MIMEPARSER_H
+#define ZORBA_EMAILMODULE_MIMEPARSER_H
+
+#include "mime_handler.h"
+
+#include "zorba/api_shared_types.h"
+
+namespace zorba { namespace emailmodule {
+
+class MimeParser
+{
+  protected:
+    MimeHandler* theHandler;
+
+  public:
+    MimeParser(MimeHandler* aHandler) : theHandler(aHandler) {};
+
+    void
+    parse(const Item& aMimeItem, std::stringstream& aDiagnostics);
+};
+
+}//namespace emailmodule
+}//namespace zorba
+
+#endif // ZORBA_EMAILMODULE_MIMEPARSER_H

=== added file 'src/com/zorba-xquery/www/modules/email/smtp.xq.src/smtp.cpp'
--- src/com/zorba-xquery/www/modules/email/smtp.xq.src/smtp.cpp	1970-01-01 00:00:00 +0000
+++ src/com/zorba-xquery/www/modules/email/smtp.xq.src/smtp.cpp	2014-04-30 23:07:12 +0000
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2006-2008 The FLWOR Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <iostream>
+#include <sstream>
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <zorba/empty_sequence.h>
+#include <zorba/diagnostic_list.h>
+#include <zorba/user_exception.h>
+#include <zorba/singleton_item_sequence.h>
+
+#include "smtp_module.h"
+#include "imap_client.h"
+#include "email_exception.h"
+#include "mime_parser.h"
+#include "smtp.h"
+
+namespace zorba { namespace emailmodule {
+
+SendFunction::SendFunction(const SmtpModule* aModule)
+  : SmtpFunction(aModule)
+{
+}
+    
+ItemSequence_t
+SendFunction::evaluate(
+  const ExternalFunction::Arguments_t& args,
+  const StaticContext* aSctxCtx,
+  const DynamicContext* aDynCtx) const
+{
+  try {
+    // getting host, username and password 
+    String lHostName, lUserName, lPassword;
+    getHostUserPassword(args, 0, lHostName, lUserName, lPassword);      
+        
+    std::stringstream lDiagnostics; 
+    // getting message as item
+    Item messageItem;
+    Iterator_t arg1_iter = args[1]->getIterator();
+    arg1_iter->open();
+    arg1_iter->next(messageItem);
+    arg1_iter->close();
+        
+    CClientMimeHandler lHandler;
+    MimeParser lParser(&lHandler);
+    lParser.parse(messageItem, lDiagnostics);
+
+    bool lHasRecipient = (lHandler.getEnvelope()->to ||
+                          lHandler.getEnvelope()->cc ||
+                          lHandler.getEnvelope()->bcc);
+
+    if (!lHasRecipient) {
+      throw EmailException("NO_RECIPIENT", "Message has no recipient.");
+    } else {
+      bool lRes = ImapClient::Instance().send(
+        lHostName.c_str(), lUserName.c_str(), lPassword.c_str(),
+        lHandler.getEnvelope(), lHandler.getBody(), lDiagnostics);
+      if (!lRes) {
+        std::stringstream lReport;
+        lReport
+          << "Message could not be sent. Reason: "
+          << lDiagnostics.str();
+        throw EmailException("NOT_SENT", lReport.str());
+      }
+    }
+  } catch (EmailException& e) {
+    raiseSmtpError(e);
+  }
+  return ItemSequence_t(NULL);
+}
+    
+} // namespace emailmodule
+} // namespace zorba
+
+#ifdef WIN32
+#  define DLL_EXPORT __declspec(dllexport)
+#else
+#  define DLL_EXPORT __attribute__ ((visibility("default")))
+#endif
+
+extern "C" DLL_EXPORT zorba::ExternalModule* createModule() {
+  return new zorba::emailmodule::SmtpModule();
+}

=== added file 'src/com/zorba-xquery/www/modules/email/smtp.xq.src/smtp.h'
--- src/com/zorba-xquery/www/modules/email/smtp.xq.src/smtp.h	1970-01-01 00:00:00 +0000
+++ src/com/zorba-xquery/www/modules/email/smtp.xq.src/smtp.h	2014-04-30 23:07:12 +0000
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2006-2008 The FLWOR Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ZORBA_EMAILMODULE_SMTP_H
+#define ZORBA_EMAILMODULE_SMTP_H
+
+#include <zorba/zorba_string.h>
+
+#include "smtp_function.h"
+
+namespace zorba { namespace emailmodule {
+
+class SendFunction : public SmtpFunction
+{
+  public:
+    SendFunction(const SmtpModule* aModule);
+
+    virtual String
+    getLocalName() const { return "send-impl"; }
+
+    virtual ItemSequence_t
+    evaluate(
+      const ExternalFunction::Arguments_t& args,
+      const StaticContext* aSctxCtx,
+      const DynamicContext* aDynCtx) const;
+
+};
+
+} // namespace emailmodule
+} // namespace zorba
+
+#endif // ZORBA_EMAILMODULE_SMTP_H

=== added file 'src/com/zorba-xquery/www/modules/email/smtp.xq.src/smtp_function.cpp'
--- src/com/zorba-xquery/www/modules/email/smtp.xq.src/smtp_function.cpp	1970-01-01 00:00:00 +0000
+++ src/com/zorba-xquery/www/modules/email/smtp.xq.src/smtp_function.cpp	2014-04-30 23:07:12 +0000
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2006-2008 The FLWOR Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <zorba/zorba.h>
+#include <zorba/iterator.h>
+#include <zorba/item_sequence.h>
+#include <zorba/user_exception.h>
+#include <zorba/xquery_functions.h>
+#include <zorba/store_consts.h>
+
+#include "smtp_function.h"
+
+#include "smtp_module.h"
+
+namespace zorba { namespace emailmodule {
+
+SmtpFunction::SmtpFunction(const SmtpModule* aModule)
+  : theModule(aModule)
+{
+}
+
+SmtpFunction::~SmtpFunction()
+{
+}
+
+void
+SmtpFunction::raiseSmtpError(EmailException& e) const
+{
+  std::string lCode;
+  if (e.get_localname() == "PARSE_ERROR") {
+    lCode = "SMTP0001";
+  }
+  else if (e.get_localname() == "NO_RECIPIENT") {
+    lCode = "SMTP0002";
+  }
+  else if (e.get_localname() == "NOT_SENT") {
+    lCode = "SMTP0003";
+  }
+  else {
+    lCode = "SMTP9999";
+  }
+  raiseSmtpError(lCode, e.get_message());
+}
+
+void
+SmtpFunction::raiseSmtpError(
+  const std::string& aQName,
+  const std::string& aMessage) const
+{
+  std::stringstream lErrorMessage;
+  lErrorMessage << aMessage;
+  Item lQName = theModule->getItemFactory()->createQName(getURI(), "smtp", aQName);
+  throw USER_EXCEPTION(lQName, lErrorMessage.str());
+}
+
+String
+SmtpFunction::getURI() const
+{
+  return theModule->getURI();
+}
+
+void 
+SmtpFunction::getHostUserPassword(
+  const ExternalFunction::Arguments_t& aArgs,
+  int aPos,
+  String& aHostName,
+  String& aUserName,
+  String& aPassword) const
+{
+  Item lNode;
+  Iterator_t lArgsIter = aArgs[aPos]->getIterator();
+  lArgsIter->open();
+  lArgsIter->next(lNode);
+  lArgsIter->close();
+
+  Item lChild;
+  Iterator_t lChildIter = lNode.getChildren();
+  lChildIter->open();
+
+  // now read the children but skipping non-element nodes
+  while (lChildIter->next(lChild)) {
+    if (lChild.getNodeKind() == store::StoreConsts::elementNode) {
+      break;
+    }
+  }
+  aHostName = lChild.getStringValue();
+  while (lChildIter->next(lChild)) {
+    if (lChild.getNodeKind() == store::StoreConsts::elementNode) {
+      break;
+    }
+  }
+  aUserName = lChild.getStringValue();
+  while (lChildIter->next(lChild)) {
+    if (lChild.getNodeKind() == store::StoreConsts::elementNode) {
+      break;
+    }
+  }
+  aPassword = lChild.getStringValue();
+  lChildIter->close();  
+}
+
+} // namespace emailmodule
+} // namespace zorba

=== added file 'src/com/zorba-xquery/www/modules/email/smtp.xq.src/smtp_function.h'
--- src/com/zorba-xquery/www/modules/email/smtp.xq.src/smtp_function.h	1970-01-01 00:00:00 +0000
+++ src/com/zorba-xquery/www/modules/email/smtp.xq.src/smtp_function.h	2014-04-30 23:07:12 +0000
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2006-2008 The FLWOR Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ZORBA_EMAILMODULE_SMTPFUNCTION_H
+#define ZORBA_EMAILMODULE_SMTPFUNCTION_H
+
+#include <zorba/function.h>
+
+#include <email_exception.h>
+
+namespace zorba { namespace emailmodule {
+
+class SmtpModule;
+
+class SmtpFunction : public ContextualExternalFunction
+{
+  protected:
+    const SmtpModule* theModule;
+
+  public:
+    void
+    raiseSmtpError(
+      EmailException& e) const;
+
+    void
+    raiseSmtpError(
+      const std::string& qName,
+      const std::string& message) const;
+
+    virtual void 
+    getHostUserPassword(
+      const ExternalFunction::Arguments_t& aArgs,
+      int aPos,
+      String& aHostName,
+      String& aUserName,
+      String& aPassword) const;
+
+  public:
+    SmtpFunction(const SmtpModule* aModule);
+    ~SmtpFunction();
+
+    virtual String
+    getURI() const;
+
+}; //class SmtpFunction
+
+} // namespace email
+} // namespace zorba
+
+#endif // ZORBA_EMAILMODULE_SMTPFUNCTION_H

=== added file 'src/com/zorba-xquery/www/modules/email/smtp.xq.src/smtp_module.cpp'
--- src/com/zorba-xquery/www/modules/email/smtp.xq.src/smtp_module.cpp	1970-01-01 00:00:00 +0000
+++ src/com/zorba-xquery/www/modules/email/smtp.xq.src/smtp_module.cpp	2014-04-30 23:07:12 +0000
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2006-2008 The FLWOR Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "smtp_module.h"
+
+#include "smtp.h"
+#include "smtp_function.h"
+
+namespace zorba { namespace emailmodule {
+
+ItemFactory* SmtpModule::theFactory = 0;
+
+SmtpModule::~SmtpModule()
+{
+  FuncMap_t::const_iterator lIter = theFunctions.begin();
+  for (; lIter != theFunctions.end(); ++lIter) {
+    delete lIter->second;
+  }
+
+  theFunctions.clear();
+}
+
+String
+SmtpModule::getURIString()
+{
+  return "http://www.zorba-xquery.com/modules/email/smtp";;
+}
+    
+ExternalFunction*
+SmtpModule::getExternalFunction(const String& aLocalname)
+{
+  ExternalFunction*& lFunc = theFunctions[aLocalname];
+  if (!lFunc) {
+    if (aLocalname == "send-impl") {
+      lFunc = new SendFunction(this);
+    }
+  }
+  return lFunc;
+}
+
+void
+SmtpModule::destroy()
+{
+  if (!dynamic_cast<SmtpModule*>(this)) {
+    return;
+  }
+  delete this;
+}
+
+} // namespace email
+} // namespace zorba

=== added file 'src/com/zorba-xquery/www/modules/email/smtp.xq.src/smtp_module.h'
--- src/com/zorba-xquery/www/modules/email/smtp.xq.src/smtp_module.h	1970-01-01 00:00:00 +0000
+++ src/com/zorba-xquery/www/modules/email/smtp.xq.src/smtp_module.h	2014-04-30 23:07:12 +0000
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2006-2008 The FLWOR Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ZORBA_EMAILMODULE_SMTPMODULE_H
+#define ZORBA_EMAILMODULE_SMTPMODULE_H
+
+#include <map>
+
+#include <zorba/zorba.h>
+#include <zorba/external_module.h>
+
+namespace zorba { namespace emailmodule {
+
+class SmtpModule : public ExternalModule
+{
+  private:
+    static ItemFactory* theFactory;
+
+  protected:
+    class ltstr
+    {
+      public:
+        bool
+        operator()(const String& s1, const String& s2) const
+        {
+          return s1.compare(s2) < 0;
+        }
+    };
+
+    typedef std::map<String, ExternalFunction*, ltstr> FuncMap_t;
+    FuncMap_t theFunctions;
+
+  public:
+    virtual ~SmtpModule();
+
+    virtual String
+    getURI() const { return SmtpModule::getURIString(); }
+      
+    static String
+    getURIString();
+
+    static ItemFactory*
+    getItemFactory()
+    {
+      if(!theFactory)
+        theFactory = Zorba::getInstance(0)->getItemFactory();
+      return theFactory;
+    }
+
+    virtual ExternalFunction*
+    getExternalFunction(const String& aLocalname);
+
+    virtual void
+    destroy();
+
+};
+
+} /* namespace emailmodule */
+} /* namespace zorba */
+
+#endif // ZORBA_EMAILMODULE_SMTPMODULE_H


References