예제 #1
0
 public async Task<ParseResult> Parse(MessageReader reader, ContentType type = ContentType.Text,
     ContentSubtype subtype = ContentSubtype.Plain, Boundary boundary = null)
 {
     headers = new Headers(entity, type, subtype);
     if ((await headers.Parse(reader)) == ParseResult.Failed)
         return ParseResult.Failed;
     content = new Content(entity);
     ParseResult result = await content.Parse(reader, headers.contentType, headers.contentSubtype,
         (headers.boundary != null) ? headers.boundary : boundary);
     return result;
 }
예제 #2
0
 public async Task<ParseResult> Parse(MessageReader reader)
 {
     // parse until empty line, which start the body
     String line = "";
     bool foundContentType = false;
     bool boundaryRequired = false;
     // could there be an empty line in FWS? I think just crlf is not allowed in FWS
     // if starts with the blank line then there is no header
     // ends with blank line
     // there are empty lines before the headers start. how many?
     bool first = true;
     while ((line = await reader.ReadLineAsync()) != null && (first || !first && line != ""))
     {
         first = false;
         if (line != "")
             WriteWithCrlf(line);
         else
             continue;
         // hack, could there be a header line not matching 
         if (!Regex.IsMatch(line, "^([^ :]+[ ]*:)|([ \t]+)"))
         {
             return ParseStatus(ParseResult.Failed, "invalid headers");
         }
         else if (foundContentType && boundaryRequired && boundary == null)
         {
             boundary = Boundary.Parse(line);
         }
         else if (foundContentType == false)
         {
             Match m = re_content.Match(line);
             if (m.Success)
             {
                 ContentType type = ContentType.Text;
                 ContentSubtype subtype = ContentSubtype.Plain;
                 String tp = m.Groups[1].Value.ToLower();
                 String sbtp = m.Groups[2].Value.ToLower();
                 if (types.TryGetValue(tp, out type) == true)
                     contentType = type;
                 else
                     contentType = ContentType.Other;
                 if (subtypes.TryGetValue(sbtp, out subtype) == true)
                     contentSubtype = subtype;
                 else
                     contentSubtype = ContentSubtype.Other;
                 contentTypeFullStr = (tp==""?"text":tp) + "/" + (sbtp==""?"plain":sbtp);
                 foundContentType = true;
                 if (contentType == ContentType.Multipart)
                 {
                     boundaryRequired = true;
                     boundary = Boundary.Parse(m.Groups[3].Value);
                 }
             }
         }
     }
     if (boundaryRequired)
     {
         if (boundary == null)
             return ParseStatus(ParseResult.Failed, "multipart media part with no boundary");
         else
             Boundary.Add(boundary);
     }
     SetSize();
     WriteCrlf(); // delimeter between headers and body, not part of the headers, so not included in size
     if (line == null)
         return ParseResult.Eof;
     else
         return ParseResult.Ok;
 }
예제 #3
0
 public async Task<ParseResult> Parse(MessageReader reader, ContentType type = ContentType.Text,
     ContentSubtype subtype = ContentSubtype.Plain, Boundary boundary = null)
 {
     if (type == ContentType.Multipart)
     {
         dataType = DataType.Multipart;
         while (true)
         {
             String line = await reader.ReadLineAsync();
             if (line == null)
             {
                 SetSize();
                 return ParseResult.Eof;
             }
             else if (EmailParser.IsPostmark(line))
             {
                 // consumed too much, probably missing boundary?
                 reader.PushCacheLine(line);
                 SetSize();
                 return ParseResult.Postmark;
             }
             WriteWithCrlf(line);
             // find open boundary
             if (boundary.IsOpen(line))
             {
                 Email email = null;
                 ParseResult res;
                 do
                 {
                     // consume all parts, consisting of header (optional) and content
                     // the boundary token delimets the part
                     // the close boundary completes multipart parsing
                     // content in the multipart is responsible for consuming it's delimeter (end)
                     // exception is the last part which is also multipart
                     email = new Email(entity);
                     Add(email);
                 } while ((res = await email.Parse(reader, type, subtype, boundary)) == ParseResult.OkMultipart); // Ok
                 // if the last part is a multipart or message? itself then it doesn't consume the close boundary
                 // or more parts, continue parsing until all parts and close boundary are consumed
                 /*if (Ok(res) && (data.Last<Email>().content.dataType == DataType.Multipart ||
                         data.Last<Email>().content.dataType == DataType.Message))*/
                 if (res == ParseResult.Ok && boundary.NotClosed())
                     continue;
                 if (res != ParseResult.Failed)
                     SetSize();
                 return res;
             }
             else if (boundary.IsClose(line, reader))
             {
                 SetSize();
                 return ParseResult.Ok; // OkMultipart
             }
         }
     }
     else if (type == ContentType.Message)
     {
         dataType = DataType.Message;
         Email email = new Email(entity);
         Add(email);
         ParseResult res = await email.Parse(reader, type, subtype, boundary);
         if (res != ParseResult.Failed)
             SetSize();
         return res;
     }
     else
     {
         dataType = DataType.Data;
         while (true)
         {
             String line = await reader.ReadLineAsync();
             if (line == null)
             {
                 SetSize();
                 return ParseResult.Eof;
             }
             else if (EmailParser.IsPostmark(line))
             {
                 // consumed too much, probably closing boundary is missing ?
                 reader.PushCacheLine(line);
                 SetSize();
                 return ParseResult.Postmark;
             }
             else if (boundary != null && boundary.IsOpen(line))
             {
                 SetSize();
                 RewindLastCrlfSize();
                 WriteWithCrlf(line);
                 return ParseResult.OkMultipart; //Ok
             }
             else if (boundary != null && boundary.IsClose(line, reader))
             {
                 SetSize();
                 RewindLastCrlfSize();
                 WriteWithCrlf(line);
                 return ParseResult.Ok; //OkMultipart
             }
             else
                 WriteWithCrlf(line);
         }
     }
 }
예제 #4
0
 public static void Add(Boundary boundary)
 {
     boundaries.Add(boundary);
 }
예제 #5
0
 public Headers(MemoryStream entity, ContentType outerType = ContentType.Text, ContentSubtype outerSubtype = ContentSubtype.Plain):base(entity)
 {
     if (outerType == ContentType.Multipart && outerSubtype == ContentSubtype.Digest)
     {
         contentType = ContentType.Message;
         contentSubtype = ContentSubtype.Rfc822;
         contentTypeFullStr = "message/rfc822";
     } else
     {
         contentType = ContentType.Text;
         contentSubtype = ContentSubtype.Plain;
         contentTypeFullStr = "text/plain";
     }
     boundary = null;
 }
예제 #6
0
 void RemoveBoundary(Boundary boundary)
 {
     // close boundary removes all boundaries up in the stack, handles missing close boundary
     int i = boundaries.FindLastIndex(b => b.boundary == boundary.boundary);
     if (i >= 0)
         boundaries.RemoveRange(i, boundaries.Count - i);
 }
예제 #7
0
        public async Task <ParseResult> Parse(MessageReader reader, ContentType type = ContentType.Text,
                                              ContentSubtype subtype = ContentSubtype.Plain, Boundary boundary = null)
        {
            headers = new Headers(entity, type, subtype);
            if ((await headers.Parse(reader)) == ParseResult.Failed)
            {
                return(ParseResult.Failed);
            }
            content = new Content(entity);
            ParseResult result = await content.Parse(reader, headers.contentType, headers.contentSubtype,
                                                     (headers.boundary != null)?headers.boundary : boundary);

            return(result);
        }
예제 #8
0
        public async Task <ParseResult> Parse(MessageReader reader, ContentType type = ContentType.Text,
                                              ContentSubtype subtype = ContentSubtype.Plain, Boundary boundary = null)
        {
            if (type == ContentType.Multipart)
            {
                dataType = DataType.Multipart;
                while (true)
                {
                    String line = await reader.ReadLineAsync();

                    if (line == null)
                    {
                        SetSize();
                        return(ParseResult.Eof);
                    }
                    else if (EmailParser.IsPostmark(line))
                    {
                        // consumed too much, probably missing boundary?
                        reader.PushCacheLine(line);
                        SetSize();
                        return(ParseResult.Postmark);
                    }
                    WriteWithCrlf(line);
                    // find open boundary
                    if (boundary.IsOpen(line))
                    {
                        Email       email = null;
                        ParseResult res;
                        do
                        {
                            // consume all parts, consisting of header (optional) and content
                            // the boundary token delimets the part
                            // the close boundary completes multipart parsing
                            // content in the multipart is responsible for consuming it's delimeter (end)
                            // exception is the last part which is also multipart
                            email = new Email(entity);
                            Add(email);
                        } while ((res = await email.Parse(reader, type, subtype, boundary)) == ParseResult.OkMultipart); // Ok
                        // if the last part is a multipart or message? itself then it doesn't consume the close boundary
                        // or more parts, continue parsing until all parts and close boundary are consumed

                        /*if (Ok(res) && (data.Last<Email>().content.dataType == DataType.Multipart ||
                         *      data.Last<Email>().content.dataType == DataType.Message))*/
                        if (res == ParseResult.Ok && boundary.NotClosed())
                        {
                            continue;
                        }
                        if (res != ParseResult.Failed)
                        {
                            SetSize();
                        }
                        return(res);
                    }
                    else if (boundary.IsClose(line, reader))
                    {
                        SetSize();
                        return(ParseResult.Ok); // OkMultipart
                    }
                }
            }
            else if (type == ContentType.Message)
            {
                dataType = DataType.Message;
                Email email = new Email(entity);
                Add(email);
                ParseResult res = await email.Parse(reader, type, subtype, boundary);

                if (res != ParseResult.Failed)
                {
                    SetSize();
                }
                return(res);
            }
            else
            {
                dataType = DataType.Data;
                while (true)
                {
                    String line = await reader.ReadLineAsync();

                    if (line == null)
                    {
                        SetSize();
                        return(ParseResult.Eof);
                    }
                    else if (EmailParser.IsPostmark(line))
                    {
                        // consumed too much, probably closing boundary is missing ?
                        reader.PushCacheLine(line);
                        SetSize();
                        return(ParseResult.Postmark);
                    }
                    else if (boundary != null && boundary.IsOpen(line))
                    {
                        SetSize();
                        RewindLastCrlfSize();
                        WriteWithCrlf(line);
                        return(ParseResult.OkMultipart); //Ok
                    }
                    else if (boundary != null && boundary.IsClose(line, reader))
                    {
                        SetSize();
                        RewindLastCrlfSize();
                        WriteWithCrlf(line);
                        return(ParseResult.Ok); //OkMultipart
                    }
                    else
                    {
                        WriteWithCrlf(line);
                    }
                }
            }
        }
예제 #9
0
        public async Task <ParseResult> Parse(MessageReader reader)
        {
            // parse until empty line, which start the body
            String line             = "";
            bool   foundContentType = false;
            bool   boundaryRequired = false;
            // could there be an empty line in FWS? I think just crlf is not allowed in FWS
            // if starts with the blank line then there is no header
            // ends with blank line
            // there are empty lines before the headers start. how many?
            bool first = true;

            while ((line = await reader.ReadLineAsync()) != null && (first || !first && line != ""))
            {
                first = false;
                if (line != "")
                {
                    WriteWithCrlf(line);
                }
                else
                {
                    continue;
                }
                // hack, could there be a header line not matching
                if (!Regex.IsMatch(line, "^([^ :]+[ ]*:)|([ \t]+)"))
                {
                    return(ParseStatus(ParseResult.Failed, "invalid headers"));
                }
                else if (foundContentType && boundaryRequired && boundary == null)
                {
                    boundary = Boundary.Parse(line);
                }
                else if (foundContentType == false)
                {
                    Match m = re_content.Match(line);
                    if (m.Success)
                    {
                        ContentType    type    = ContentType.Text;
                        ContentSubtype subtype = ContentSubtype.Plain;
                        String         tp      = m.Groups[1].Value.ToLower();
                        String         sbtp    = m.Groups[2].Value.ToLower();
                        if (types.TryGetValue(tp, out type) == true)
                        {
                            contentType = type;
                        }
                        else
                        {
                            contentType = ContentType.Other;
                        }
                        if (subtypes.TryGetValue(sbtp, out subtype) == true)
                        {
                            contentSubtype = subtype;
                        }
                        else
                        {
                            contentSubtype = ContentSubtype.Other;
                        }
                        contentTypeFullStr = (tp == ""?"text":tp) + "/" + (sbtp == ""?"plain":sbtp);
                        foundContentType   = true;
                        if (contentType == ContentType.Multipart)
                        {
                            boundaryRequired = true;
                            boundary         = Boundary.Parse(m.Groups[3].Value);
                        }
                    }
                }
            }
            if (boundaryRequired)
            {
                if (boundary == null)
                {
                    return(ParseStatus(ParseResult.Failed, "multipart media part with no boundary"));
                }
                else
                {
                    Boundary.Add(boundary);
                }
            }
            SetSize();
            WriteCrlf(); // delimeter between headers and body, not part of the headers, so not included in size
            if (line == null)
            {
                return(ParseResult.Eof);
            }
            else
            {
                return(ParseResult.Ok);
            }
        }
예제 #10
0
 public static void Add(Boundary boundary)
 {
     boundaries.Add(boundary);
 }