bool ParseBodyStructure(string sMessageUID, ref string sBodyStruct, XmlTextWriter oXmlBodyPart,
string sPartPrefix, bool bFetchBody)
{
bool bMultiPart = false;
string sTemp = "";
ArrayList asAttrs = new ArrayList();
sBodyStruct = sBodyStruct.Trim();
//Check if this is NIL
if (IsNilString (ref sBodyStruct))
return true;
//Look for '('
if (sBodyStruct[0] == '(')
{
//Check if multipart or singlepart.
//Multipart will have another '(' here
// and single part will not.
char ch;
ch = sBodyStruct[1];
if (ch != '(')
{
//Singal part
if (ch == ')')
{
sBodyStruct = sBodyStruct.Substring(2);
return true;
}
//remove opening paranthesis
sBodyStruct = sBodyStruct.Substring(1);
string sType = "";
string sSubType = "";
if (!GetContentType(ref sBodyStruct, ref sType, ref sSubType, ref sTemp))
{
return false;
}
asAttrs.Add(IMAP_MESSAGE_CONTENT_TYPE);
asAttrs.Add(sTemp);
// Message-id (optional)
if (!ParseQuotedString( ref sBodyStruct, ref sTemp ))
{
Log(LogTypeEnum.ERROR, "Failed getting Message Id.");
return false;
}
if (sTemp.Length > 0)
{
asAttrs.Add(IMAP_MESSAGE_ID);
asAttrs.Add(sTemp);
}
// Content-Description (optional)
if (!ParseQuotedString( ref sBodyStruct, ref sTemp ))
{
Log(LogTypeEnum.ERROR, "Failed getting the Content Desc.");
return false;
}
if (sTemp.Length > 0)
{
asAttrs.Add(IMAP_MESSAGE_CONTENT_DESC);
asAttrs.Add(sTemp);
}
// Content-Transfer-Encoding
if (!ParseQuotedString( ref sBodyStruct, ref sTemp ))
{
Log(LogTypeEnum.ERROR, "Failed getting the Content Encoding.");
return false;
}
asAttrs.Add(IMAP_MESSAGE_CONTENT_ENCODING);
asAttrs.Add(sTemp);
// Content Size in bytes
if (!ParseString( ref sBodyStruct, ref sTemp ))
{
Log(LogTypeEnum.ERROR, "Failed getting the Content Size.");
return false;
}
asAttrs.Add(IMAP_MESSAGE_CONTENT_SIZE);
asAttrs.Add(sTemp);
sTemp = sType + "/" + sSubType;
if (sTemp.ToLower() == IMAP_MESSAGE_RFC822.ToLower()) //email attachment
{
if (!ParseEnvelope(ref sBodyStruct, asAttrs ))
{
Log(LogTypeEnum.ERROR, "Failed getting the Message Envelope.");
return false;
}
if (!ParseBodyStructure(sMessageUID, ref sBodyStruct, oXmlBodyPart,
sPartPrefix, bFetchBody ))
{
Log (LogTypeEnum.ERROR, "Failed getting Attached Message.");
return false;
}
// No of Lines in the message
if (!ParseString(ref sBodyStruct, ref sTemp ))
{
Log(LogTypeEnum.ERROR, "Failed getting the Content Lines.");
return false;
}
if (sTemp.Length > 0)
{
asAttrs.Add(IMAP_MESSAGE_CONTENT_LINES);
asAttrs.Add(sTemp);
}
}
else if (sType == "text") //simple text
{
// No of Lines in the message
if (!ParseString(ref sBodyStruct, ref sTemp ))
{
Log(LogTypeEnum.ERROR, "Failed getting the Content Lines.");
return false;
}
if (sTemp.Length > 0)
{
asAttrs.Add(IMAP_MESSAGE_CONTENT_LINES);
asAttrs.Add(sTemp);
}
}
// MD5 CRC Error Check
// Don't know what to do with it
if (sBodyStruct[0] == ' ')
{
if (!ParseString( ref sBodyStruct, ref sTemp ))
return false;
}
}
else // MULTIPART
{
bMultiPart = true;
// remove the open paranthesis
sBodyStruct = sBodyStruct.Substring(1);
uint nPartNumber = 0;
string sPartNumber= "";
do
{
// prepare next part number
nPartNumber++;
if (sPartPrefix.Length > 0)
sPartNumber = sPartPrefix + "." + nPartNumber.ToString();
else
sPartNumber = nPartNumber.ToString();
//XmlElement oXmlChildPart;
oXmlBodyPart.WriteStartElement("Part");
oXmlBodyPart.WriteAttributeString("ID",sPartNumber);
// add a new child to the part with
// an empty attribute array. This array will be filled
// in the "if" condition block.
int nCount = asAttrs.Count;
for (int i = 0; i < nCount; i = i + 2)
{
oXmlBodyPart.WriteElementString(asAttrs[i].ToString(),asAttrs[i + 1].ToString());
}
if (sPartNumber.Length > 0 &&
sPartNumber != "0" &&
bFetchBody == true)
{
try
{
string sData = "";
GetBody(sMessageUID, sPartNumber, ref sData);
if (sData.Length > 0 &&
((sData.ToLower()).IndexOf(IMAP_MESSAGE_CONTENT_TYPE.ToLower()) == -1))
{
oXmlBodyPart.WriteElementString("DATA", sData);
}
}
catch (ImapException e)
{
Log(LogTypeEnum.ERROR, "Exception:Invalid Body Structure. Error:" + e.Message);
return false;
}
}
// add a new child to the part with
// an empty attribute array. This array will be filled
// in the "if" condition block.
//oXmlBodyPart.AppendChild(oXmlChildPart);
// parse this body part
if (!ParseBodyStructure(sMessageUID, ref sBodyStruct, oXmlBodyPart,
sPartNumber, bFetchBody))
{
return false;
}
oXmlBodyPart.WriteEndElement();
}
while (sBodyStruct[0] == '('); // For each body part
// Content-type
string sType = IMAP_MESSAGE_MULTIPART;
string sSubType = "";
if (!GetContentType(ref sBodyStruct, ref sType, ref sSubType,
ref sTemp ))
{
return false;
}
asAttrs.Add(IMAP_MESSAGE_CONTENT_TYPE);
asAttrs.Add(sTemp);
}
//----------------------------------
// COMMON FOR SINGLE AND MULTI PART
// Disposition
if (sBodyStruct[0] == ' ')
{
if (!GetContentDisposition(ref sBodyStruct, ref sTemp ))
{
Log(LogTypeEnum.ERROR, "Failed getting the Content Disp.");
return false;
}
if (sTemp.Length > 0)
{
asAttrs.Add(IMAP_MESSAGE_CONTENT_DISP);
asAttrs.Add(sTemp);
}
}
// Language
if (sBodyStruct[0] == ' ')
{
if (!ParseLanguage(ref sBodyStruct, ref sTemp ))
return false;
}
// Extension data
while (sBodyStruct[0] == ' ')
if (!ParseExtension(ref sBodyStruct, ref sTemp ))
return false;
// this is the end of the body part
if (!FindAndRemove(ref sBodyStruct, ')' ))
return false;
// Finally, set the attribute array to the part
// EXCEPTION : if multipart and this is the root
// part, the header is already prepared in the
// GetBodyStructure function and hence DO NOT set it.
if (!bMultiPart || sPartPrefix.Length > 0)
{
int nCount = asAttrs.Count;
for (int i = 0; i < nCount ; i= i+2)
{
oXmlBodyPart.WriteElementString(asAttrs[i].ToString(), asAttrs[i+1].ToString());
}
}
return true;
}
Log (LogTypeEnum.ERROR, "Invalid Body Structure");
return false;
}