Сохранения письма в БД.
#38374643
Ссылка:
Ссылка на сообщение:
Ссылка с названием темы:
Ссылка на профиль пользователя:
|
|
|
Arm79код древний, и ради выкладывания на форуме причесывать не буду
По факту: дерево строится в момент парсинга. Каждый MailPart содержит свою инфу и список всех частей.
Перебор: сначала сделал рекурсию, потом выкинул, решил, что в библиотеке это не нужно. Это сторона ответственности вызывающего кода.
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. 91. 92. 93. 94. 95. 96. 97. 98. 99. 100. 101. 102. 103. 104. 105. 106. 107. 108. 109. 110. 111. 112. 113. 114. 115. 116. 117. 118. 119. 120. 121. 122. 123. 124. 125. 126. 127. 128. 129. 130. 131. 132. 133. 134. 135. 136. 137. 138. 139. 140. 141. 142. 143. 144. 145. 146. 147. 148. 149. 150.
/// <summary>
/// Класс, инкапсулирующий работу с частью письма
/// </summary>
public sealed class MailPart
{
#region Private Members
private readonly string _rawData;
private readonly string _text;
private readonly MailPartHeader _header;
private readonly MailAttachment _attachment;
private readonly List<MailPart> _pairs;
/// <summary>
/// Выбор строки произвольной заголовка по ее имени
/// </summary>
/// <param name="headerEntries">Исходный список, в котором нужно вести поиск</param>
/// <param name="paramName">Произвольное имя параметра</param>
/// <returns>Параметр со значениями</returns>
private static MailPartHeaderEntry GetHeaderEntry(IEnumerable<MailPartHeaderEntry> headerEntries, string paramName)
{
if (headerEntries == null)
return null;
var findedEntries = headerEntries.Where(_he => _he.Name == paramName.ToUpper());
return findedEntries.Count() != 0? findedEntries.First() : null;
}
#endregion
#region Properties
public string ContentType
{
get { return _header.ContentType; }
}
public string CharSet
{
get { return _header.CharSet; }
}
public MailPartHeader Header
{
get { return _header; }
}
public string Text
{
get { return _text; }
}
public MailAttachment Attachment
{
get { return _attachment; }
}
public IList<MailPart> Parts
{
get { return _pairs.AsReadOnly(); }
}
#endregion
#region .ctor
public MailPart(string rawData)
{
_rawData = rawData;
_pairs = new List<MailPart>();
// делим на две зоны
var terminator = _rawData.IndexOf("\r\n\r\n");
var header = (terminator != -1) ? _rawData.Substring(0, terminator) : _rawData;
var body = (terminator != -1) ? _rawData.Substring(terminator + 4) : string.Empty;
// парсим заголовок
_header = new MailPartHeader(header);
// парсим тело
// 1) Является ли тело вложением?
var contentDisposition = GetHeaderEntry(_header.HeaderEntries, "Content-Disposition");
if (contentDisposition != null)
{
if (contentDisposition.Value == "attachment")
{
var fileName = GetHeaderEntry(contentDisposition.SubEntries, "filename");
var contentType = GetHeaderEntry(_header.HeaderEntries, "Content-Type");
var contentDescription = GetHeaderEntry(_header.HeaderEntries, "Content-Description");
var contentEncoding = GetHeaderEntry(_header.HeaderEntries, "Content-Transfer-Encoding");
var name = contentType != null ? GetHeaderEntry(contentType.SubEntries, "name") : null;
_attachment = new MailAttachment(
body,
_header.CharSet,
contentEncoding != null ? MimeParser.GetTextWithoutQuotes(contentEncoding.Value) : "7bit",
name != null ? name.Value : string.Empty,
fileName != null ? fileName.Value : string.Empty,
contentDescription != null ? contentDescription.Value : String.Empty);
}
}
else
{
// 2) Является ли многочастевым?
if (_header.ContentType.StartsWith("multipart"))
{
// Определяем границу
var ct = GetHeaderEntry(_header.HeaderEntries, "Content-Type");
if (ct == null)
throw new ApplicationException("Невозможно определить тэг ContentType, чтобы из него получить границы");
var b = GetHeaderEntry(ct.SubEntries, "boundary");
if (b == null)
throw new ApplicationException(string.Format("не найдены границы, хотя ContentType={0}", _header.ContentType));
string boundary = "--" + MimeParser.GetTextWithoutQuotes(b.Value);
// берем нужные кусочеки и превращаем их в пары
var begin = body.IndexOf(string.Format("\r\n{0}", boundary)) + boundary.Length + 2 /*передние \r\n*/ + 2 /*задние \r\n*/;
var end = body.IndexOf(string.Format("{0}--\r\n", boundary), begin);
_pairs.AddRange(
body
.Substring(begin, end - begin)
.Split(new string[] { string.Format("\r\n{0}", boundary) }, StringSplitOptions.RemoveEmptyEntries)
.Select( _s => new MailPart(_s)));
}
else
{
// 3) Голый текст
byte[] _buffer;
var contentEncoding = GetHeaderEntry(_header.HeaderEntries, "Content-Transfer-Encoding");
switch (contentEncoding != null ? contentEncoding.Value : "7bit")
{
case "base64":
_buffer = MimeParser.FromBase64Encoding(body);
break;
case "quoted-printable":
_buffer = MimeParser.FromQuotedPrintableEncoding(body);
break;
case "8bit":
_buffer = MimeParser.ConvertTo8BitBinary(CharSet, body);
break;
default:
_buffer = MimeParser.ConvertTo7BitBinary(body);
break;
}
_text = Encoding.GetEncoding(CharSet).GetString(_buffer);
}
}
}
#endregion
}
Спасибо
|
|