private MimeEntityReturnCode ProcessMimeEntity(MailMessageParser message, string parentBoundaryStart)
{
bool hasParentBoundary = parentBoundaryStart.Length > 0;
string parentBoundaryEnd = parentBoundaryStart + ServiceConstants.HYPHEN + ServiceConstants.HYPHEN;
MimeEntityReturnCode boundaryMimeReturnCode;
////some format fields are inherited from parent, only the default for
////ContentType needs to be set here, otherwise the boundary parameter would be
////inherited as well
message.SetContentTypeFields(ServiceConstants.MAIL_CONTENT_TYPE);
string completeHeaderField = null; ////consists of one start line and possibly several continuation lines
string response;
//// read header lines until empty line is found (end of header)
while (true)
{
if (!this.ReadMultipleLine(out response))
{
while (this.ReadMultipleLine(out response))
{
continue;
}
return MimeEntityReturnCode.problem;
}
if (1 > response.Length)
{
////empty line found => end of header
if (completeHeaderField != null)
{
this.ProcessHeaderField(message, completeHeaderField);
}
break;
}
if (hasParentBoundary && ParentBoundaryFound(response, parentBoundaryStart, parentBoundaryEnd, out boundaryMimeReturnCode))
{
while (this.ReadMultipleLine(out response))
{
continue;
}
return boundaryMimeReturnCode;
}
////read header field
////one header field can extend over one start line and multiple continuation lines
////a continuation line starts with at least 1 blank (' ') or tab
if (ServiceConstants.SPACE == Convert.ToString(response[0], CultureInfo.InvariantCulture) || ServiceConstants.HORIZONTAL_TAB == Convert.ToString(response[0], CultureInfo.InvariantCulture))
{
if (completeHeaderField == null)
{
while (this.ReadMultipleLine(out response))
{
continue;
}
return MimeEntityReturnCode.problem;
}
else
{
if (ServiceConstants.SPACE != Convert.ToString(completeHeaderField[completeHeaderField.Length - 1], CultureInfo.InvariantCulture))
{
completeHeaderField += ServiceConstants.SPACE + response.TrimStart(whiteSpaceChars);
}
else
{
completeHeaderField += response.TrimStart(whiteSpaceChars);
}
}
}
else
{
if (null == completeHeaderField)
{
completeHeaderField = response;
}
else
{
this.ProcessHeaderField(message, completeHeaderField);
completeHeaderField = response;
}
}
}
this.mimeEntitySB.Length = 0;
string boundaryDelimiterLineStart = null;
bool isBoundaryDefined = false;
if (null != message.ContentType.Boundary)
{
isBoundaryDefined = true;
boundaryDelimiterLineStart = "--" + message.ContentType.Boundary;
}
////prepare return code for the case there is no boundary in the body
boundaryMimeReturnCode = MimeEntityReturnCode.bodyComplete;
////read body lines
while (this.ReadMultipleLine(out response))
{
////check if there is a boundary line from this entity itself in the body
if (isBoundaryDefined && response.TrimEnd() == boundaryDelimiterLineStart)
{
////boundary line found.
////stop the processing here and start a delimited body processing
return this.ProcessDelimitedBody(message, boundaryDelimiterLineStart, parentBoundaryStart, parentBoundaryEnd);
}
////check if there is a parent boundary in the body
if (hasParentBoundary &&
ParentBoundaryFound(response, parentBoundaryStart, parentBoundaryEnd, out boundaryMimeReturnCode))
{
////a parent boundary is found. Decode the content of the body received so far, then end this MIME entity
////note that boundaryMimeReturnCode is set here, but used in the return statement
break;
}
////process next line
this.mimeEntitySB.Append(response + this.CRLF);
}
////a complete MIME body read
////convert received US ASCII characters to .NET string (Unicode)
string transferEncodedMessage = Convert.ToString(this.mimeEntitySB, CultureInfo.InvariantCulture);
bool isAttachmentSaved = false;
switch (message.ContentTransferEncoding)
{
case TransferEncoding.SevenBit:
SaveMessageBody(message, transferEncodedMessage);
break;
case TransferEncoding.Base64:
byte[] bodyBytes = System.Convert.FromBase64String(transferEncodedMessage);
message.ContentStream = new MemoryStream(bodyBytes, false);
if (message.MediaMainType == ServiceConstants.TEXT_MEDIA_MAIN_TYPE)
{
message.Body = DecodeByteArrayToString(bodyBytes, message.BodyEncoding);
}
else if (message.MediaMainType == ServiceConstants.IMAGE_MEDIA_MAIN_TYPE || message.MediaMainType == ServiceConstants.APPLICATION_MEDIA_MAIN_TYPE || message.MediaMainType == ServiceConstants.MESSAGE_MEDIA_MAIN_TYPE)
{
SaveAttachment(message);
isAttachmentSaved = true;
}
break;
case TransferEncoding.QuotedPrintable:
SaveMessageBody(message, QuotedPrintable.Decode(transferEncodedMessage));
break;
default:
SaveMessageBody(message, transferEncodedMessage);
break;
}
if (null != message.ContentDisposition && message.ContentDisposition.DispositionType.ToUpperInvariant() == ServiceConstants.MailAttributes.ATTACHMENT && !isAttachmentSaved)
{
SaveAttachment(message);
isAttachmentSaved = true;
}
return boundaryMimeReturnCode;
}