Holy IMAP folder Batman!

Ok, anyone around here ever had to deal with IMAP folder names?
Outside the US?
For non – US client?

You might have noticed, that the array of folder names returned by IMAP_ListMBs may contain funny stuff like

INBOX.Gel&APY-schte Elemente

or

INBOX.batman&ZeVnLIqe-.&U,BTFw-robin

never seen those?
never cared?
what’s IMAP?
use english words, dumdum!

otherwise: read on

Just to clarify:

INBOX.Gel&APY-schte Elemente -> INBOX.Gelöschte Elemente

and

INBOX.batman&ZeVnLIqe-.&U,BTFw-robin -> INBOX.batman日本語/台北robin

Just checked, the Japanese in the example above contains no profanity, at least according to google translate…

The encoding is UTF-7, but with a twist only used in IMAP for mailbox names.

If you really want to know what this is, read the corresponding RFC : rfc3501 or don’t, it’s boring and hard to grasp, as are all RFCs…

Sadly yours truly had to wade through this pit of encoding abomination but I had some help from other german colleagues, the final tip came from Matthias Schmidt (thanks again).

In my everlasting and saintlike generosity I hereby share the results with you in case somebody else gets lost in mailbox name translation hell:

// ----------------------------------------------------
// Method: CUrlUtil_DecodeUTF7MBox
// ----------------------------------------------------
// Call:   $t_MBoxName:=CUrlUtil_DecodeUTF7MBox(MBoxNameEncoded)
// ----------------------------------------------------
//        [ ] theadsafe
// ----------------------------------------------------
// UserName (OS): Alexander Heintz
// Date and Time: 11.07.17, 12:18:04
// ----------------------------------------------------
// Does:
//      decodes a special format UTF-7 used ONLY for Mailbox
//      names in IMAP into UTF-8
//      Example
//      INBOX.Gel&APY-schte Elemente
//      becomes
//      INBOX.Gelöschte Elemente
// ----------------------------------------------------
// Parameters:
// ->  $1     text        the encoded mailbox name
// <-  $0     text        the decoded mailbox name
// ----------------------------------------------------
// Parameter Definition
C_TEXT($1)
C_TEXT($0)
// ----------------------------------------------------
// Local Variable Definition
C_BOOLEAN($b_Passed)
C_TEXT($t_Result)
C_TEXT($t_Text)
// ----------------------------------------------------
// Parameter Assignment
$t_Text:=$1
// ----------------------------------------------------


//do some preparatory replaces
//replace commas within encoded parts with slashes
$l_Start:=1
While (Match regex("(?<=\\&)(.*?)(?=\\-)";$t_Text;$l_Start;$l_Pos;$l_Len))
$t_Part:=Substring($t_Text;$l_Pos;$l_Len)
  If (Position(",";$t_Part)>0)
$t_Part:=Replace string($t_Part;",";"/")
$t_Text:=Change string($t_Text;$t_Part;$l_Pos)
  End if 
$l_Start:=$l_Pos+$l_Len
End while 
//literal +
$t_Text:=Replace string($t_Text;"+";"+-")
//literal &
$t_Text:=Replace string($t_Text;"&-";"+ACY-")
//replace shift character
$t_Text:=Replace string($t_Text;"&";"+")
$b_Passed:=PHP Execute("";"iconv";$t_Result;"UTF-7";"UTF-8";$t_Text)
$0:=Choose($b_Passed;$t_Result;$t_Text)

And the other direction:

// ----------------------------------------------------
// Method: CUrlUtil_EncodeUTF7MBox
// ----------------------------------------------------
// Call:   MBoxNameEncoded:=CUrlUtil_EncodeUTF7MBox(MBoxName)
// ----------------------------------------------------
//        [ ] theadsafe
// ----------------------------------------------------
// UserName (OS): Alexander Heintz
// Date and Time: 11.07.17, 12:17:41
// ----------------------------------------------------
// Does:
//      encodes a special format UTF-7 used ONLY for Mailbox
//      names in IMAP from UTF-8
//      Example
//      INBOX.Gelöschte Elemente
//      becomes
//      INBOX.Gel&APY-schte Elemente
// ----------------------------------------------------
// Parameters:
// ->  $1     text        the decoded mailbox name
// <-  $0     text        the encoded mailbox name
// ----------------------------------------------------
// Parameter Definition
C_TEXT($1)
C_TEXT($0)
// ----------------------------------------------------
// Local Variable Definition
C_BOOLEAN($b_Passed)
C_TEXT($t_Result)
C_TEXT($t_Text)
// ----------------------------------------------------
// Parameter Assignment
$t_Text:=$1
// ----------------------------------------------------


$b_Passed:=PHP Execute("";"iconv";$t_Result;"UTF-8";"UTF-7";$t_Text)
If ($b_Passed)
//do the required replaces
//literal + obfuscate for the moment
$t_Result:=Replace string($t_Result;"+-";"###")
//literal &
$t_Result:=Replace string($t_Result;"+ACY-";"&-")
//replace shift character
$t_Result:=Replace string($t_Result;"+";"&")
//literal + de obfuscate and set
$t_Result:=Replace string($t_Result;"###";"+")
//replace the slashes in the shifted parts with commas
$l_Start:=1
While (Match regex("(?<=\\&)(.*?)(?=\\-)";$t_Result;$l_Start;$l_Pos;$l_Len))
$t_Part:=Substring($t_Result;$l_Pos;$l_Len)
If (Position("/";$t_Part)>0)
$t_Part:=Replace string($t_Part;"/";",")
$t_Result:=Change string($t_Result;$t_Part;$l_Pos)
End if 
$l_Start:=$l_Pos+$l_Len
End while 
End if 
$0:=Choose($b_Passed;$t_Result;$t_Text)

As always, code is presented as is and no guarantees given or responsibilities taken!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.