/*
最近写了一个自动收邮件的机器人,原来一开始偷懒 "娶" 了 COM 组件 JMail:
《 封装 JMail 4.4 的 POP3 为 .Net 组件 (.dll 程序集),实现 "邮件(附件) 到达" 等 "事件"! 》
后来经人介绍认识了 OpenPOP.Net
我就 移情别恋 ,再后来我们就相爱了,再后来我就 修理她 :
加一个小功能( 红色字体代码部分 ),可用于 收取邮件时监测数据流量 !
老规矩: 我的代码随便 Copy & Paste 到任意一个 .cs 文件中 csc 即可测试! (结构不好,目的就是方便测试代码)
*/
//OpenPOP.Net
namespace OpenPOP.MIMEParser
{
using System;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Collections;
using System.Globalization;
///
1<summary>
2/// Summary description for Attachment.
3/// </summary>
public class Attachment : IComparable
{
#region Member Variables
private string _contentType = null;
private string _contentCharset = null;
private string _contentFormat = null;
private string _contentTransferEncoding = null;
private string _contentDescription = null;
private string _contentDisposition = null;
private string _contentFileName = "";
private string _defaultFileName = "body.htm";
private string _defaultFileName2 = "body*.htm";
private string _defaultReportFileName = "report.htm";
private string _defaultMIMEFileName = "body.eml";
private string _defaultMSTNEFFileName = "winmail.dat";
private string _contentID = null;
private long _contentLength = 0;
private string _rawAttachment = null;
private bool _inBytes = false;
private byte[] _rawBytes = null;
#endregion
#region Properties
///
1<summary>
2/// raw attachment content bytes
3/// </summary>
public byte[] RawBytes
{
get
{
return _rawBytes;
}
set
{
_rawBytes = value;
}
}
///
1<summary>
2/// whether attachment is in bytes
3/// </summary>
public bool InBytes
{
get
{
return _inBytes;
}
set
{
_inBytes = value;
}
}
///
1<summary>
2/// Content length
3/// </summary>
public long ContentLength
{
get
{
return _contentLength;
}
}
///
1<summary>
2/// verify the attachment whether it is a real attachment or not
3/// </summary>
///
1<remarks>this is so far not comprehensive and needs more work to finish</remarks>
public bool NotAttachment
{
get
{
/* if (_contentDisposition==null||_contentType==null)
return true;
else
return (_contentDisposition.IndexOf("attachment")==-1 && _contentType.IndexOf("text/plain")!=-1); /
/ if (_contentType==null)
return true;
else
return (_contentFileName!="");*/
if ((_contentType == null || _contentFileName == "") && _contentID == null) //&&_contentType.ToLower().IndexOf("text/")!=-1)
return true;
else
return false;
}
}
///
1<summary>
2/// Content format
3/// </summary>
public string ContentFormat
{
get
{
return _contentFormat;
}
}
///
1<summary>
2/// Content charset
3/// </summary>
public string ContentCharset
{
get
{
return _contentCharset;
}
}
///
1<summary>
2/// default file name
3/// </summary>
public string DefaultFileName
{
get
{
return _defaultFileName;
}
set
{
_defaultFileName = value;
}
}
///
1<summary>
2/// default file name 2
3/// </summary>
public string DefaultFileName2
{
get
{
return _defaultFileName2;
}
set
{
_defaultFileName2 = value;
}
}
///
1<summary>
2/// default report file name
3/// </summary>
public string DefaultReportFileName
{
get
{
return _defaultReportFileName;
}
set
{
_defaultReportFileName = value;
}
}
///
1<summary>
2/// default MIME File Name
3/// </summary>
public string DefaultMIMEFileName
{
get
{
return _defaultMIMEFileName;
}
set
{
_defaultMIMEFileName = value;
}
}
///
1<summary>
2/// Content Type
3/// </summary>
public string ContentType
{
get
{
return _contentType;
}
}
///
1<summary>
2/// Content Transfer Encoding
3/// </summary>
public string ContentTransferEncoding
{
get
{
return _contentTransferEncoding;
}
}
///
1<summary>
2/// Content Description
3/// </summary>
public string ContentDescription
{
get
{
return _contentDescription;
}
}
///
1<summary>
2/// Content File Name
3/// </summary>
public string ContentFileName
{
get
{
return _contentFileName;
}
set
{
_contentFileName = value;
}
}
///
1<summary>
2/// Content Disposition
3/// </summary>
public string ContentDisposition
{
get
{
return _contentDisposition;
}
}
///
1<summary>
2/// Content ID
3/// </summary>
public string ContentID
{
get
{
return _contentID;
}
}
///
1<summary>
2/// Raw Attachment
3/// </summary>
public string RawAttachment
{
get
{
return _rawAttachment;
}
}
///
1<summary>
2/// decoded attachment in bytes
3/// </summary>
public byte[] DecodedAttachment
{
get
{
return DecodedAsBytes();
}
}
#endregion
///
1<summary>
2/// release all objects
3/// </summary>
~Attachment()
{
_rawBytes = null;
_rawAttachment = null;
}
///
1<summary>
2/// New Attachment
3/// </summary>
///
1<param name="bytAttachment"/>
attachment bytes content
///
1<param name="lngFileLength"/>
file length
///
1<param name="strFileName"/>
file name
///
1<param name="strContentType"/>
content type
public Attachment(byte[] bytAttachment, long lngFileLength, string strFileName, string strContentType)
{
_inBytes = true;
_rawBytes = bytAttachment;
_contentLength = lngFileLength;
_contentFileName = strFileName;
_contentType = strContentType;
}
///
1<summary>
2/// New Attachment
3/// </summary>
///
1<param name="bytAttachment"/>
attachment bytes content
///
1<param name="strFileName"/>
file name
///
1<param name="strContentType"/>
content type
public Attachment(byte[] bytAttachment, string strFileName, string strContentType)
{
_inBytes = true;
_rawBytes = bytAttachment;
_contentLength = bytAttachment.Length;
_contentFileName = strFileName;
_contentType = strContentType;
}
///
1<summary>
2/// New Attachment
3/// </summary>
///
1<param name="strAttachment"/>
attachment content
///
1<param name="strContentType"/>
content type
///
1<param name="blnParseHeader"/>
whether only parse the header or not
public Attachment(string strAttachment, string strContentType, bool blnParseHeader)
{
if (!blnParseHeader)
{
_contentFileName = _defaultMSTNEFFileName;
_contentType = strContentType;
}
this.NewAttachment(strAttachment, blnParseHeader);
}
///
1<summary>
2/// New Attachment
3/// </summary>
///
1<param name="strAttachment"/>
attachment content
public Attachment(string strAttachment)
{
this.NewAttachment(strAttachment, true);
}
///
1<summary>
2/// create attachment
3/// </summary>
///
1<param name="strAttachment"/>
raw attachment text
///
1<param name="blnParseHeader"/>
parse header
private void NewAttachment(string strAttachment, bool blnParseHeader)
{
_inBytes = false;
if (strAttachment == null)
throw new ArgumentNullException("strAttachment");
StringReader srReader = new StringReader(strAttachment);
if (blnParseHeader)
{
string strLine = srReader.ReadLine();
while (Utility.IsNotNullTextEx(strLine))
{
ParseHeader(srReader, ref strLine);
if (Utility.IsOrNullTextEx(strLine))
break;
else
strLine = srReader.ReadLine();
}
}
this._rawAttachment = srReader.ReadToEnd();
_contentLength = this._rawAttachment.Length;
}
///
1<summary>
2/// Parse header fields and set member variables
3/// </summary>
///
1<param name="srReader"/>
string reader
///
1<param name="strLine"/>
header line
private void ParseHeader(StringReader srReader, ref string strLine)
{
string[] array = Utility.GetHeadersValue(strLine); //Regex.Split(strLine,":");
string[] values = Regex.Split(array[1], ";"); //array[1].Split(';');
string strRet = null;
switch (array[0].ToUpper())
{
case "CONTENT-TYPE":
if (values.Length > 0)
_contentType = values[0].Trim();
if (values.Length > 1)
{
_contentCharset = Utility.GetQuotedValue(values[1], "=", "charset");
}
if (values.Length > 2)
{
_contentFormat = Utility.GetQuotedValue(values[2], "=", "format");
}
_contentFileName = Utility.ParseFileName(strLine);
if (_contentFileName == "")
{
strRet = srReader.ReadLine();
if (strRet == "")
{
strLine = "";
break;
}
_contentFileName = Utility.ParseFileName(strLine);
if (_contentFileName == "")
ParseHeader(srReader, ref strRet);
}
break;
case "CONTENT-TRANSFER-ENCODING":
_contentTransferEncoding = Utility.SplitOnSemiColon(array[1])[0].Trim();
break;
case "CONTENT-DESCRIPTION":
_contentDescription = Utility.DecodeText(Utility.SplitOnSemiColon(array[1])[0].Trim());
break;
case "CONTENT-DISPOSITION":
if (values.Length > 0)
_contentDisposition = values[0].Trim();
///
1<bug>reported by grandepuffo @ https://sourceforge.net/forum/message.php?msg_id=2589759
2//_contentFileName=values[1];
3if (values.Length > 1)
4{
5_contentFileName = values[1];
6}
7else
8{
9_contentFileName = "";
10}
11
12if (_contentFileName == "")
13_contentFileName = srReader.ReadLine();
14
15_contentFileName = _contentFileName.Replace("\t", "");
16_contentFileName = Utility.GetQuotedValue(_contentFileName, "=", "filename");
17_contentFileName = Utility.DecodeText(_contentFileName);
18break;
19case "CONTENT-ID":
20_contentID = Utility.SplitOnSemiColon(array[1])[0].Trim('<').Trim('>');
21break;
22}
23}
24
25/// <summary>
26/// verify the encoding
27/// </summary>
28/// <param name="encoding"/>encoding to verify
29/// <returns>true if encoding</returns>
30private bool IsEncoding(string encoding)
31{
32return _contentTransferEncoding.ToLower().IndexOf(encoding.ToLower()) != -1;
33}
34
35/// <summary>
36/// Decode the attachment to text
37/// </summary>
38/// <returns>Decoded attachment text</returns>
39public string DecodeAsText()
40{
41string decodedAttachment = null;
42
43try
44{
45if (_contentType.ToLower() == "message/rfc822".ToLower())
46decodedAttachment = Utility.DecodeText(_rawAttachment);
47else if (_contentTransferEncoding != null)
48{
49decodedAttachment = _rawAttachment;
50
51if (!IsEncoding("7bit"))
52{
53if (IsEncoding("8bit") && _contentCharset != null & _contentCharset != "")
54decodedAttachment = Utility.Change(decodedAttachment, _contentCharset);
55
56if (Utility.IsQuotedPrintable(_contentTransferEncoding))
57decodedAttachment = DecodeQP.ConvertHexContent(decodedAttachment);
58else if (IsEncoding("8bit"))
59decodedAttachment = decodedAttachment;
60else
61decodedAttachment = Utility.deCodeB64s(Utility.RemoveNonB64(decodedAttachment));
62}
63}
64else if (_contentCharset != null)
65decodedAttachment = Utility.Change(_rawAttachment, _contentCharset); //Encoding.Default.GetString(Encoding.GetEncoding(_contentCharset).GetBytes(_rawAttachment));
66else
67decodedAttachment = _rawAttachment;
68}
69catch
70{
71decodedAttachment = _rawAttachment;
72}
73return decodedAttachment;
74}
75
76/// <summary>
77/// decode attachment to be a message object
78/// </summary>
79/// <returns>message</returns>
80public Message DecodeAsMessage()
81{
82bool blnRet = false;
83return new Message(ref blnRet, "", false, _rawAttachment, false);
84}
85
86/// <summary>
87/// Decode the attachment to bytes
88/// </summary>
89/// <returns>Decoded attachment bytes</returns>
90public byte[] DecodedAsBytes()
91{
92if (_rawAttachment == null)
93return null;
94if (_contentFileName != "")
95{
96byte[] decodedBytes = null;
97
98if (_contentType != null && _contentType.ToLower() == "message/rfc822".ToLower())
99decodedBytes = Encoding.Default.GetBytes(Utility.DecodeText(_rawAttachment));
100else if (_contentTransferEncoding != null)
101{
102string bytContent = _rawAttachment;
103
104if (!IsEncoding("7bit"))
105{
106if (IsEncoding("8bit") && _contentCharset != null & _contentCharset != "")
107bytContent = Utility.Change(bytContent, _contentCharset);
108
109if (Utility.IsQuotedPrintable(_contentTransferEncoding))
110decodedBytes = Encoding.Default.GetBytes(DecodeQP.ConvertHexContent(bytContent));
111else if (IsEncoding("8bit"))
112decodedBytes = Encoding.Default.GetBytes(bytContent);
113else
114decodedBytes = Convert.FromBase64String(Utility.RemoveNonB64(bytContent));
115}
116else
117decodedBytes = Encoding.Default.GetBytes(bytContent);
118}
119else if (_contentCharset != null)
120decodedBytes = Encoding.Default.GetBytes(Utility.Change(_rawAttachment, _contentCharset)); //Encoding.Default.GetString(Encoding.GetEncoding(_contentCharset).GetBytes(_rawAttachment));
121else
122decodedBytes = Encoding.Default.GetBytes(_rawAttachment);
123
124return decodedBytes;
125}
126else
127{
128return null;
129}
130}
131
132public int CompareTo(object attachment)
133{
134return (this.RawAttachment.CompareTo(((Attachment) (attachment)).RawAttachment));
135}
136}
137
138public enum MessageImportanceType
139{
140HIGH = 5,
141NORMAL = 3,
142LOW = 1
143}
144
145/// <summary>
146/// Decoding Quoted-Printable text
147///
148/// </summary>
149public class DecodeQP
150{
151public DecodeQP()
152{
153}
154
155/// <summary>
156/// Decoding Quoted-Printable string
157/// </summary>
158/// <param name="Hexstring"/>Quoted-Printable encoded string
159/// <param name="encode"/>encoding method
160/// <returns>decoded string</returns>
161public static string ConvertHexToString(string Hexstring, string Encoding)
162{
163try
164{
165return ConvertHexToString(Hexstring, System.Text.Encoding.GetEncoding(Encoding));
166}
167catch
168{
169return ConvertHexContent(Hexstring);
170}
171}
172
173/// <summary>
174/// Decoding Quoted-Printable string
175/// </summary>
176/// <param name="Hexstring"/>Quoted-Printable encoded string
177/// <param name="encode"/>encoding method
178/// <returns>decoded string</returns>
179public static string ConvertHexToString(string Hexstring, Encoding encode)
180{
181try
182{
183if (Hexstring == null || Hexstring.Equals("")) return "";
184
185if (Hexstring.StartsWith("=")) Hexstring = Hexstring.Substring(1);
186
187string[] aHex = Hexstring.Split(new char[1] {'='});
188byte[] abyte = new Byte[aHex.Length];
189
190for (int i = 0; i < abyte.Length; i++)
191{
192// Console.WriteLine(aHex[i]);
193abyte[i] = (byte) int.Parse(aHex[i], NumberStyles.HexNumber);
194}
195return encode.GetString(abyte);
196}
197catch
198{
199return Hexstring;
200}
201}
202
203/// <summary>
204/// Decoding Quoted-Printable string at a position
205/// </summary>
206/// <param name="Hexstring"/>Quoted-Printable encoded string
207/// <param name="encode"/>encoding method, "Default" is suggested
208/// <param name="nStart"/>position to start, normally 0
209/// <returns>decoded string</returns>
210public static string ConvertHexContent(string Hexstring, Encoding encode, long nStart)
211{
212if (nStart >= Hexstring.Length) return Hexstring;
213
214//to hold string to be decoded
215StringBuilder sbHex = new StringBuilder();
216sbHex.Append("");
217//to hold decoded string
218StringBuilder sbEncoded = new StringBuilder();
219sbEncoded.Append("");
220//wether we reach Quoted-Printable string
221bool isBegin = false;
222string temp;
223int i = (int) nStart;
224
225while (i < Hexstring.Length)
226{
227//init next loop
228sbHex.Remove(0, sbHex.Length);
229isBegin = false;
230int count = 0;
231
232while (i < Hexstring.Length)
233{
234temp = Hexstring.Substring(i, 1); //before reaching Quoted-Printable string, one char at a time
235if (temp.StartsWith("="))
236{
237temp = Hexstring.Substring(i, 3); //get 3 chars
238if (temp.EndsWith("\r\n")) //return char
239{
240if (isBegin && (count%2 == 0))
241break;
242// sbEncoded.Append("");
243i = i + 3;
244}
245else if (!temp.EndsWith("3D"))
246{
247sbHex.Append(temp);
248isBegin = true; //we reach Quoted-Printable string, put it into buffer
249i = i + 3;
250count++;
251}
252else //if it ends with 3D, it is "="
253{
254if (isBegin && (count%2 == 0)) //wait until even items to handle all character sets
255break;
256
257sbEncoded.Append("=");
258i = i + 3;
259}
260
261}
262else
263{
264if (isBegin) //we have got the how Quoted-Printable string, break it
265break;
266sbEncoded.Append(temp); //not Quoted-Printable string, put it into buffer
267i++;
268}
269
270}
271//decode Quoted-Printable string
272sbEncoded.Append(ConvertHexToString(sbHex.ToString(), encode));
273}
274
275return sbEncoded.ToString();
276}
277
278
279/// <summary>
280/// Decoding Quoted-Printable string using default encoding and begin at 0
281/// </summary>
282/// <param name="Hexstring"/>Quoted-Printable encoded string
283/// <returns>decoded string</returns>
284public static string ConvertHexContent(string Hexstring)
285{
286if (Hexstring == null || Hexstring.Equals("")) return Hexstring;
287
288return ConvertHexContent(Hexstring, Encoding.Default, 0);
289
290}
291}
292
293/// <summary>
294/// Message Parser.
295/// </summary>
296public class Message
297{
298#region Member Variables
299
300private ArrayList _attachments = new ArrayList();
301private string _rawHeader = null;
302private string _rawMessage = null;
303private string _rawMessageBody = null;
304private int _attachmentCount = 0;
305private string _replyTo = null;
306private string _replyToEmail = null;
307private string _from = null;
308private string _fromEmail = null;
309private string _date = null;
310private string _dateTimeInfo = null;
311private string _subject = null;
312private string[] _to = new string[0];
313private string[] _cc = new string[0];
314private string[] _bcc = new string[0];
315private ArrayList _keywords = new ArrayList();
316private string _contentType = null;
317private string _contentCharset = null;
318private string _reportType = null;
319private string _contentTransferEncoding = null;
320private bool _html = false;
321private long _contentLength = 0;
322private string _contentEncoding = null;
323private string _returnPath = null;
324private string _mimeVersion = null;
325private string _received = null;
326private string _importance = null;
327private string _messageID = null;
328private string _attachmentboundry = null;
329private string _attachmentboundry2 = null;
330private bool _hasAttachment = false;
331private string _dispositionNotificationTo = null;
332private ArrayList _messageBody = new ArrayList();
333private string _basePath = null;
334private bool _autoDecodeMSTNEF = false;
335private Hashtable _customHeaders = new Hashtable();
336
337#endregion
338
339#region Properties
340
341/// <summary>
342/// custom headers
343/// </summary>
344public Hashtable CustomHeaders
345{
346get
347{
348return _customHeaders;
349}
350set
351{
352_customHeaders = value;
353}
354}
355
356/// <summary>
357/// whether auto decoding MS-TNEF attachment files
358/// </summary>
359public bool AutoDecodeMSTNEF
360{
361get
362{
363return _autoDecodeMSTNEF;
364}
365set
366{
367_autoDecodeMSTNEF = value;
368}
369}
370
371/// <summary>
372/// path to extract MS-TNEF attachment files
373/// </summary>
374public string BasePath
375{
376get
377{
378return _basePath;
379}
380set
381{
382try
383{
384if (value.EndsWith("\\\"))
385_basePath = value;
386else
387_basePath = value + "\\\";
388}
389catch
390{
391}
392}
393}
394
395/// <summary>
396/// message keywords
397/// </summary>
398public ArrayList Keywords
399{
400get
401{
402return _keywords;
403}
404}
405
406/// <summary>
407/// disposition notification
408/// </summary>
409public string DispositionNotificationTo
410{
411get
412{
413return _dispositionNotificationTo;
414}
415}
416
417/// <summary>
418/// received server
419/// </summary>
420public string Received
421{
422get
423{
424return _received;
425}
426}
427
428/// <summary>
429/// importance level
430/// </summary>
431public string Importance
432{
433get
434{
435return _importance;
436}
437}
438
439/// <summary>
440/// importance level type
441/// </summary>
442public MessageImportanceType ImportanceType
443{
444get
445{
446switch (_importance.ToUpper())
447{
448case "5":
449case "HIGH":
450return MessageImportanceType.HIGH;
451case "3":
452case "NORMAL":
453return MessageImportanceType.NORMAL;
454case "1":
455case "LOW":
456return MessageImportanceType.LOW;
457default:
458return MessageImportanceType.NORMAL;
459}
460}
461}
462
463/// <summary>
464/// Content Charset
465/// </summary>
466public string ContentCharset
467{
468get
469{
470return _contentCharset;
471}
472}
473
474/// <summary>
475/// Content Transfer Encoding
476/// </summary>
477public string ContentTransferEncoding
478{
479get
480{
481return _contentTransferEncoding;
482}
483}
484
485/// <summary>
486/// Message Bodies
487/// </summary>
488public ArrayList MessageBody
489{
490get
491{
492return _messageBody;
493}
494}
495
496/// <summary>
497/// Attachment Boundry
498/// </summary>
499public string AttachmentBoundry
500{
501get
502{
503return _attachmentboundry;
504}
505}
506
507/// <summary>
508/// Alternate Attachment Boundry
509/// </summary>
510public string AttachmentBoundry2
511{
512get
513{
514return _attachmentboundry2;
515}
516}
517
518/// <summary>
519/// Attachment Count
520/// </summary>
521public int AttachmentCount
522{
523get
524{
525return _attachmentCount;
526}
527}
528
529/// <summary>
530/// Attachments
531/// </summary>
532public ArrayList Attachments
533{
534get
535{
536return _attachments;
537}
538}
539
540/// <summary>
541/// CC
542/// </summary>
543public string[] CC
544{
545get
546{
547return _cc;
548}
549}
550
551/// <summary>
552/// BCC
553/// </summary>
554public string[] BCC
555{
556get
557{
558return _bcc;
559}
560}
561
562/// <summary>
563/// TO
564/// </summary>
565public string[] TO
566{
567get
568{
569return _to;
570}
571}
572
573/// <summary>
574/// Content Encoding
575/// </summary>
576public string ContentEncoding
577{
578get
579{
580return _contentEncoding;
581}
582}
583
584/// <summary>
585/// Content Length
586/// </summary>
587public long ContentLength
588{
589get
590{
591return _contentLength;
592}
593}
594
595/// <summary>
596/// Content Type
597/// </summary>
598public string ContentType
599{
600get
601{
602return _contentType;
603}
604}
605
606/// <summary>
607/// Report Type
608/// </summary>
609public string ReportType
610{
611get
612{
613return _reportType;
614}
615}
616
617/// <summary>
618/// HTML
619/// </summary>
620public bool HTML
621{
622get
623{
624return _html;
625}
626}
627
628/// <summary>
629/// Date
630/// </summary>
631public string Date
632{
633get
634{
635return _date;
636}
637}
638
639/// <summary>
640/// DateTime Info
641/// </summary>
642public string DateTimeInfo
643{
644get
645{
646return _dateTimeInfo;
647}
648}
649
650/// <summary>
651/// From name
652/// </summary>
653public string From
654{
655get
656{
657return _from;
658}
659}
660
661/// <summary>
662/// From Email
663/// </summary>
664public string FromEmail
665{
666get
667{
668return _fromEmail;
669}
670}
671
672/// <summary>
673/// Reply to name
674/// </summary>
675public string ReplyTo
676{
677get
678{
679return _replyTo;
680}
681}
682
683/// <summary>
684/// Reply to email
685/// </summary>
686public string ReplyToEmail
687{
688get
689{
690return _replyToEmail;
691}
692}
693
694/// <summary>
695/// whether has attachment
696/// </summary>
697public bool HasAttachment
698{
699get
700{
701return _hasAttachment;
702}
703}
704
705/// <summary>
706/// raw message body
707/// </summary>
708public string RawMessageBody
709{
710get
711{
712return _rawMessageBody;
713}
714}
715
716/// <summary>
717/// Message ID
718/// </summary>
719public string MessageID
720{
721get
722{
723return _messageID;
724}
725}
726
727/// <summary>
728/// MIME version
729/// </summary>
730public string MimeVersion
731{
732get
733{
734return _mimeVersion;
735}
736}
737
738/// <summary>
739/// raw header
740/// </summary>
741public string RawHeader
742{
743get
744{
745return _rawHeader;
746}
747}
748
749/// <summary>
750/// raw message
751/// </summary>
752public string RawMessage
753{
754get
755{
756return _rawMessage;
757}
758}
759
760/// <summary>
761/// return path
762/// </summary>
763public string ReturnPath
764{
765get
766{
767return _returnPath;
768}
769}
770
771/// <summary>
772/// subject
773/// </summary>
774public string Subject
775{
776get
777{
778return _subject;
779}
780}
781
782#endregion
783
784/// <summary>
785/// release all objects
786/// </summary>
787~Message()
788{
789_attachments.Clear();
790_attachments = null;
791_keywords.Clear();
792_keywords = null;
793_messageBody.Clear();
794_messageBody = null;
795_customHeaders.Clear();
796_customHeaders = null;
797}
798
799/// <summary>
800/// New Message
801/// </summary>
802/// <param name="blnFinish"/>reference for the finishing state
803/// <param name="strBasePath"/>path to extract MS-TNEF attachment files
804/// <param name="blnAutoDecodeMSTNEF"/>whether auto decoding MS-TNEF attachments
805/// <param name="blnOnlyHeader"/>whether only decode the header without body
806/// <param name="strEMLFile"/>file of email content to load from
807public Message(ref bool blnFinish, string strBasePath, bool blnAutoDecodeMSTNEF, bool blnOnlyHeader, string strEMLFile)
808{
809string strMessage = null;
810if (Utility.ReadPlainTextFromFile(strEMLFile, ref strMessage))
811{
812NewMessage(ref blnFinish, strBasePath, blnAutoDecodeMSTNEF, strMessage, blnOnlyHeader);
813}
814else
815blnFinish = true;
816}
817
818/// <summary>
819/// New Message
820/// </summary>
821/// <param name="blnFinish"/>reference for the finishing state
822/// <param name="strBasePath"/>path to extract MS-TNEF attachment files
823/// <param name="blnAutoDecodeMSTNEF"/>whether auto decoding MS-TNEF attachments
824/// <param name="strMessage"/>raw message content
825/// <param name="blnOnlyHeader"/>whether only decode the header without body
826public Message(ref bool blnFinish, string strBasePath, bool blnAutoDecodeMSTNEF, string strMessage, bool blnOnlyHeader)
827{
828NewMessage(ref blnFinish, strBasePath, blnAutoDecodeMSTNEF, strMessage, blnOnlyHeader);
829}
830
831/// <summary>
832/// New Message
833/// </summary>
834/// <param name="blnFinish"/>reference for the finishing state
835/// <param name="strMessage"/>raw message content
836/// <param name="blnOnlyHeader"/>whether only decode the header without body
837public Message(ref bool blnFinish, string strMessage, bool blnOnlyHeader)
838{
839NewMessage(ref blnFinish, "", false, strMessage, blnOnlyHeader);
840}
841
842/// <summary>
843/// New Message
844/// </summary>
845/// <param name="blnFinish"/>reference for the finishing state
846/// <param name="strMessage"/>raw message content
847public Message(ref bool blnFinish, string strMessage)
848{
849NewMessage(ref blnFinish, "", false, strMessage, false);
850}
851
852/// <summary>
853/// get valid attachment
854/// </summary>
855/// <param name="intAttachmentNumber"/>attachment index in the attachments collection
856/// <returns>attachment</returns>
857public Attachment GetAttachment(int intAttachmentNumber)
858{
859if (intAttachmentNumber < 0 || intAttachmentNumber > _attachmentCount || intAttachmentNumber > _attachments.Count)
860{
861Utility.LogError("GetAttachment():attachment not exist");
862throw new ArgumentOutOfRangeException("intAttachmentNumber");
863}
864return (Attachment) _attachments[intAttachmentNumber];
865}
866
867/// <summary>
868/// New Message
869/// </summary>
870/// <param name="blnFinish"/>reference for the finishing state
871/// <param name="strBasePath"/>path to extract MS-TNEF attachment files
872/// <param name="blnAutoDecodeMSTNEF"/>whether auto decoding MS-TNEF attachments
873/// <param name="strMessage"/>raw message content
874/// <param name="blnOnlyHeader"/>whether only decode the header without body
875/// <returns>construction result whether successfully new a message</returns>
876private bool NewMessage(ref bool blnFinish, string strBasePath, bool blnAutoDecodeMSTNEF, string strMessage, bool blnOnlyHeader)
877{
878StringReader srdReader = new StringReader(strMessage);
879StringBuilder sbdBuilder = new StringBuilder();
880_basePath = strBasePath;
881_autoDecodeMSTNEF = blnAutoDecodeMSTNEF;
882
883_rawMessage = strMessage;
884
885string strLine = srdReader.ReadLine();
886while (Utility.IsNotNullTextEx(strLine))
887{
888sbdBuilder.Append(strLine + "\r\n");
889ParseHeader(sbdBuilder, srdReader, ref strLine);
890if (Utility.IsOrNullTextEx(strLine))
891break;
892else
893strLine = srdReader.ReadLine();
894}
895
896_rawHeader = sbdBuilder.ToString();
897
898SetAttachmentBoundry2(_rawHeader);
899
900if (_contentLength == 0)
901_contentLength = strMessage.Length; //_rawMessageBody.Length;
902
903if (blnOnlyHeader == false)
904{
905_rawMessageBody = srdReader.ReadToEnd().Trim();
906
907//the auto reply mail by outlook uses ms-tnef format
908if ((_hasAttachment == true && _attachmentboundry != null) || MIMETypes.IsMSTNEF(_contentType))
909{
910set_attachments();
911
912if (this.Attachments.Count > 0)
913{
914Attachment at = this.GetAttachment(0);
915if (at != null && at.NotAttachment)
916this.GetMessageBody(at.DecodeAsText());
917else
918{
919}
920//in case body parts as text[0] html[1]
921if (this.Attachments.Count > 1 && !this.IsReport())
922{
923at = this.GetAttachment(1);
924if (at != null && at.NotAttachment)
925this.GetMessageBody(at.DecodeAsText());
926else
927{
928}
929}
930}
931else
932{
933}
934}
935else
936{
937GetMessageBody(_rawMessageBody);
938}
939}
940
941blnFinish = true;
942return true;
943}
944
945/// <summary>
946/// parse message body
947/// </summary>
948/// <param name="strBuffer"/>raw message body
949/// <returns>message body</returns>
950public string GetTextBody(string strBuffer)
951{
952if (strBuffer.EndsWith("\r\n."))
953return strBuffer.Substring(0, strBuffer.Length - "\r\n.".Length);
954else
955return strBuffer;
956}
957
958/// <summary>
959/// parse message body
960/// </summary>
961/// <param name="strBuffer"/>raw message body
962public void GetMessageBody(string strBuffer)
963{
964int end, begin;
965string body;
966string encoding = "";
967
968begin = end = 0;
969_messageBody.Clear();
970
971try
972{
973if (Utility.IsOrNullTextEx(strBuffer))
974return;
975else if (Utility.IsOrNullTextEx(_contentType) && _contentTransferEncoding == null)
976{
977_messageBody.Add(GetTextBody(strBuffer));
978}
979else if (_contentType != null && _contentType.IndexOf("digest") >= 0)
980{
981// this is a digest method
982//ParseDigestMessage(strBuffer);
983_messageBody.Add(GetTextBody(strBuffer));
984}
985else if (_attachmentboundry2 == null)
986{
987body = GetTextBody(strBuffer);
988
989if (Utility.IsQuotedPrintable(_contentTransferEncoding))
990{
991body = DecodeQP.ConvertHexContent(body);
992}
993else if (Utility.IsBase64(_contentTransferEncoding))
994{
995body = Utility.deCodeB64s(Utility.RemoveNonB64(body));
996}
997else if (Utility.IsNotNullText(_contentCharset))
998{
999body = Encoding.GetEncoding(_contentCharset).GetString(Encoding.Default.GetBytes(body));
1000}
1001_messageBody.Add(Utility.RemoveNonB64(body));
1002}
1003else
1004{
1005begin = 0;
1006
1007while (begin != -1)
1008{
1009// find "\r\n\r\n" denoting end of header
1010begin = strBuffer.IndexOf("--" + _attachmentboundry2, begin);
1011if (begin != -1)
1012{
1013encoding = MIMETypes.GetContentTransferEncoding(strBuffer, begin);
1014
1015begin = strBuffer.IndexOf("\r\n\r\n", begin + 1); //strBuffer.LastIndexOfAny(ALPHABET.ToCharArray());
1016
1017// find end of text
1018end = strBuffer.IndexOf("--" + _attachmentboundry2, begin + 1);
1019
1020if (begin != -1)
1021{
1022if (end != -1)
1023{
1024begin += 4;
1025if (begin >= end)
1026continue;
1027else if (this._contentEncoding != null && this._contentEncoding.IndexOf("8bit") != -1)
1028body = Utility.Change(strBuffer.Substring(begin, end - begin - 2), _contentCharset);
1029else
1030body = strBuffer.Substring(begin, end - begin - 2);
1031}
1032else
1033{
1034body = strBuffer.Substring(begin);
1035}
1036
1037if (Utility.IsQuotedPrintable(encoding))
1038{
1039string ret = body;
1040ret = DecodeQP.ConvertHexContent(ret);
1041_messageBody.Add(ret);
1042}
1043else if (Utility.IsBase64(encoding))
1044{
1045string ret = Utility.RemoveNonB64(body);
1046ret = Utility.deCodeB64s(ret);
1047if (ret != "\0")
1048_messageBody.Add(ret);
1049else
1050_messageBody.Add(body);
1051}
1052else
1053_messageBody.Add(body);
1054
1055if (end == -1) break;
1056}
1057else
1058{
1059break;
1060}
1061}
1062else
1063{
1064if (_messageBody.Count == 0)
1065{
1066_messageBody.Add(strBuffer);
1067}
1068break;
1069}
1070}
1071}
1072}
1073catch (Exception e)
1074{
1075Utility.LogError("GetMessageBody():" + e.Message);
1076_messageBody.Add(Utility.deCodeB64s(strBuffer));
1077}
1078
1079if (_messageBody.Count > 1)
1080_html = true;
1081}
1082
1083/// <summary>
1084/// verify if the message is a report
1085/// </summary>
1086/// <returns>if it is a report message, return true, else, false</returns>
1087public bool IsReport()
1088{
1089if (Utility.IsNotNullText(_contentType))
1090return (_contentType.ToLower().IndexOf("report".ToLower()) != -1);
1091else
1092return false;
1093}
1094
1095/// <summary>
1096/// verify if the attachment is MIME Email file
1097/// </summary>
1098/// <param name="attItem"/>attachment
1099/// <returns>if MIME Email file, return true, else, false</returns>
1100public bool IsMIMEMailFile(Attachment attItem)
1101{
1102try
1103{
1104return (attItem.ContentFileName.ToLower().EndsWith(".eml".ToLower()) || attItem.ContentType.ToLower() == "message/rfc822".ToLower());
1105}
1106catch (Exception e)
1107{
1108Utility.LogError("IsMIMEMailFile():" + e.Message);
1109return false;
1110}
1111}
1112
1113/// <summary>
1114/// translate pictures url within the body
1115/// </summary>
1116/// <param name="strBody"/>message body
1117/// <param name="hsbFiles"/>pictures collection
1118/// <returns>translated message body</returns>
1119public string TranslateHTMLPictureFiles(string strBody, Hashtable hsbFiles)
1120{
1121try
1122{
1123for (int i = 0; i < this.AttachmentCount; i++)
1124{
1125Attachment att = this.GetAttachment(i);
1126if (Utility.IsPictureFile(att.ContentFileName) == true)
1127{
1128if (Utility.IsNotNullText(att.ContentID))
1129//support for embedded pictures
1130strBody = strBody.Replace("cid:" + att.ContentID, hsbFiles[att.ContentFileName].ToString());
1131
1132strBody = strBody.Replace(att.ContentFileName, hsbFiles[att.ContentFileName].ToString());
1133}
1134}
1135}
1136catch (Exception e)
1137{
1138Utility.LogError("TranslateHTMLPictureFiles():" + e.Message);
1139}
1140return strBody;
1141}
1142
1143/// <summary>
1144&nb</summary></bug>