async Task TraverseEmail(StreamWriter filew, int id, int part, Email email) { await WriteStatsLine(filew, "part: {0}", part); int csize = await CompressedSize(email.headers.GetBytes()); await WriteStatsLine(filew, "headers: {0} {1} {2}", email.headers.GetNumberOfHeaders(), email.headers.size, csize); await WriteStatsLine(filew, "contenttype: {0}", email.headers.contentTypeFullStr); switch (email.content.dataType) { case DataType.Data: if (email.headers.contentType == ContentType.Audio || email.headers.contentType == ContentType.Video || email.headers.contentType == ContentType.Image || email.headers.contentType == ContentType.Application) { byte[] buff = email.content.GetBytes(); csize = await CompressedSize(buff); String sha1 = Sha1(buff); await WriteStatsLine(filew, "attachment: {0} {1} {2}", sha1, email.content.size, csize); } else { csize = await CompressedSize(email.content.GetBytes()); await WriteStatsLine(filew, "body: {0} {1}", email.content.size, csize); } break; case DataType.Message: await WriteStatsLine(filew, "start rfc822: {0}", id); await TraverseEmail(filew, (id + 1), 0, email.content.data[0]); await WriteStatsLine(filew, "end rfc822: {0}", id); break; case DataType.Multipart: await WriteStatsLine(filew, "start multipart {0} {1}:", id, email.content.data.Count); int p = 0; foreach (Email e in email.content.data) await TraverseEmail(filew, id + 1, p++, e); await WriteStatsLine(filew, "end multipart {0}", id); break; } }
public static void TraverseEmail(Email email) { String headers = email.headers.GetString(); ContentType ctype = email.headers.contentType; DataType dtype = email.content.dataType; int size = email.content.size; switch (dtype) { case DataType.Data: String content = email.content.GetString(); break; case DataType.Message: case DataType.Multipart: foreach (Email e in email.content.data) TraverseEmail(e); break; default: break; } return; }
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); } } }
/* Assume (for now) the message starts with the postmark, Further assume the message structure postmark\r\n headers\r\n \r\n body */ public async Task<ParseResult> Parse(MessageReader reader) { postmark = new Postmark(entity); if ((await postmark.Parse(reader)) == ParseResult.Failed) throw new ParsingFailedException("postmark is not found"); email = new Email(entity); ParseResult res = await email.Parse(reader); if (res != ParseResult.Eof && res != ParseResult.Postmark) await ConsumeToEnd(reader); SetSize(); return res; }
void Add(Email email) { if (data == null) data = new List<Email>(); data.Add(email); }