Usability - Productivity - Business - The web - Singapore & Twins

Driving Embedded Experiences Adoption

With the introduction of Connections Mail and IBM Notes 9.0 a brand new productivity feature was made available in eMail: Embedded Experiences (EE). They are defined by the Open Social Foundation and can also be found in IBM Connections or Atlassian's Confluence Wiki.
The use case for embedded experiences in eMail is simple:
" Any application that sends a notification message to your attention and/or action can reduce the time and clicks required for processing by taking advantage of an embedded experience"
Ryan described in detail how to switch on the processing of embedded experiences and the Wiki tells how how to use XPages to send them. The trouble with this: you need to touch every single application that sends out a notification. You might not have time, budget or source code access to them.
So are EE a nice idea, but confined to some niche applications?
Not at all! When peeking under the hood, you can see, that an EE enabled eMail has a HTML and a JSON Mime part. If a client doesn't understand EE (like mobile clients or any other eMail than IBM Notes), then the HTML message is rendered. Important here: even with Notes you must have a HTML part, a plain text message won't do. Using a "when new mail arrives" agent, you can turn an incoming message into an EE.
As long as the target system supports one of the authentications the Account API provides (Basic HTTP, JEE Form, SAML, Spengo, OS Credential, Siteminder, LTPA) this will work. This is Notes client only, for Connections or iNotes you are limited to SAML.
First thought was to use a "Before mail arrives" agent to make sure, that the mail gets delivered fully converted. However such an agent runs in the router context and might be a performance killer - the when new mail arrives option seems a suitable compromise. The approach works with signed eMails too, since signing covers the eMail body, but not headers and mime separators (you can't sign the header since each routing hop adds information there).
As an example I used a plain text eMail, that sends a notification with a number of field/values separated by colon and containing only one URL. For your use cases, you will need to adopt the code (or wait for a future blog, just saying). Since my original message only contained text/plain I had to add text/html and application/json mime parts.The Notes API MimeEntity class makes the code rather simple and does the conversion in less than 100 lines of code. It will work for any notification following this pattern.
Sub ConvertToEE (s AsNotesSession, doc AsNotesDocument)
    Dim body AsNotesMIMEEntity
    Dim parent AsNotesMIMEEntity
    Dim header AsNotesMIMEHeader
    Dim jsonEE AsNotesMIMEEntity
    Dim htmlEE AsNotesMIMEEntity
    Dim jsonStream AsNotesStream
    Dim htmlStream AsNotesStream
    Dim content AsNotesStream

    Dim headerName AsString
    Dim headerValue AsString
    Dim newHeaders ListAsString
    Set content = s. Createstream()
    Set jsonStream = s. Createstream()
    Set htmlStream = s. Createstream()
    s. Convertmime = False
    Set body = doc. Getmimeentity("Body")
    Call body. Getcontentastext(content, True)
    Set parent = body. Createparententity()
    Call addHeader (parent, "Content-Type", "multipart/alternative")
    Call addHeader (parent, "MIME-Version", "1.0")
    Call generateEEParts (content,jsonStream,htmlStream )

    jsonStream. position = 0
    Set jsonEE = parent. Createchildentity()
    Call jsonEE. Setcontentfromtext(jsonStream, "application/embed+json;charset=UTF-8", ENC_IDENTITY_7BIT )
    htmlStream. position = 0
    Set htmlEE = parent. Createchildentity()
    Call htmlEE. Setcontentfromtext(htmlStream, "text/html;charset=UTF-8", ENC_IDENTITY_7BIT )
    Call doc. Replaceitemvalue("containsEE", "URL")
    Call doc. Save(true, true)
    s. Convertmime = true
    Sub generateEEParts
    Description: Creates the body content for

Sub generateEEParts (stream AsNotesStream, outJSON AsNotesStream, outHTML AsNotesStream)
    Dim workstring AsString
    Dim url AsString
    Dim ParamName AsString
    Dim ParamValue AsString
    Dim position AsInteger
    Dim isFirst AsBoolean
    Dim eolChars ListAsInteger
    Dim eolPos AsInteger
    Dim i AsInteger
    Dim x AsString
    eolChars (0) = 10
    eolChars (1) = 13
    eolChars (2) = 42
    'Create the URL
    Call outHTML. writeText(|<h1 style="background-color : Yellow; font-family: Verdana, Arial, sans-serif">Workflow notification (URL)</h1>|,EOL_PLATFORM )
    Call outHTML. writeText(|<table border="0" cellpadding="2" cellspacing="2">|,EOL_PLATFORM )
    Call outHTML. writeText(|<tr><th style="border : 1px solid gray; font-family: Verdana, Arial, sans-serif">Parameter</th><th style="border: 1px solid gray; font-family: Verdana, Arial, sans-serif">Value</th></tr>|,EOL_PLATFORM )
    'Loop through all the items
    stream. Position = 0
    workstring = stream. Readtext(STMREAD_LINE , EOL_ANY )
    isFirst = true
    DoUntil workString = ""
        For eolPos = 1ToLen(workString )
            x = x + CStr(Asc(Mid$(workstring,eolPos, 1)))+ "-"
        'Cleanup workstring - remove 10/13 combinations
        ForAll curChar In eolChars
            eolPos = InStr(workstring, Chr$(curChar ))
            While(eolPos > 0)
                workstring = Left$(workstring,eolPos- 1)
                eolPos = InStr(workstring, Chr$(curChar ))

        position = InStr(workstring, ":")
        If position > 0Then
            'We have a line with a Name / Value Pair
            ParamName = Replace(Trim$(Left$(workstring,position- 1)), |"|, |\"|)
            ParamValue = Replace(Trim$(Mid$(workstring,position+ 1)), |"|, |\"|)
            IfLeft$(ParamValue, 4) = "http"Then
                Call outJSON. writeText(|{ "url"  : "|+ParamValue+ |" }|,EOL_PLATFORM )
            Call outHTML. writeText(|<tr><td style="border: 1px solid gray; font-family: Verdana, Arial, sans-serif">|,EOL_PLATFORM )
            Call outHTML. writeText(ParamName,EOL_PLATFORM )
            Call outHTML. writeText(|</td><td style="border-bottom : 1px solid gray; border-right: 1px solid gray; font-family: Verdana, Arial, sans-serif">|,EOL_PLATFORM )
            Call outHTML. writeText(ParamValue,EOL_PLATFORM )
            Call outHTML. writeText(|</td></tr>|,EOL_PLATFORM )
        workstring = stream. Readtext(STMREAD_LINE , EOL_Platform )
    'Write out the closing
    Call outHTML. writeText(|</table>|,EOL_PLATFORM )
Sub addHeader (mime AsNotesMIMEEntity, hName AsString, value AsString)
        Dim header AsNotesMIMEHeader
        Set header = mime. CreateHeader(hName )
        If header IsNothingThen
            Set header = mime. Getnthheader(hname )
        Call header. SetHeaderVal(value )
As usual: YMMV

Posted by on 03 November 2013 | Comments (3) | categories: IBM Notes XPages


  1. posted by Stephan Wissel on Monday 04 November 2013 AD:
    @David, I just checked, and there are Gadgets listed for embedded experiences in a pretty plain Confluence installation, so they are there (just google it). Also the documetation for OpenSocial is in Confluence.

    Emoticon biggrin.gif stw
  2. posted by Robert Ibsen Voith on Monday 04 November 2013 AD:
    Thanks for sharing! Most interesting - and very timely!
  3. posted by David Simpson on Monday 04 November 2013 AD:
    Hi Stephan, thanks for posting this. A minor correction Atlassian Confluence does not have embedded experience inbuilt.

    Emoticon smile.gif