public void Initialize(string addres, string pass) { _client = new Pop3MimeClient("pop.gmail.com", 995, true, addres, pass); _client.Trace += new TraceHandler(client_Trace); _client.Warning += new WarningHandler(client_Warning); _client.ReadTimeout = 60000; //give pop server 60 seconds to answer }
static void Main(string[] args) { // TODO: Remove the comment signs from the next line, if you want to create some sample emails. // SendTestmail(); //If you get a run time error her: SmtpFailedRecipientException, 'Mailbox unavailable. The server response was: 5.7.1 Unable to relay for', //then you need to change the settings of the local IIS/SMTP server. Console.WriteLine("POP3 MIME Client Demo"); Console.WriteLine("====================="); Console.WriteLine(); XmlConfigurator.Configure(new FileInfo("Log4net.config")); Pop3MimeClient DemoClient = new Pop3MimeClient("pop.gmail.com", 995, true, "*****@*****.**", "elvis3012"); //DemoClient.Trace += new TraceHandler(Console.WriteLine); DemoClient.Trace += new TraceHandler((s) => log.Debug(s)); DemoClient.Warning += new WarningHandler((s, z) => log.Warn(s + " " + z)); DemoClient.ReadTimeout = 60000; //give pop server 60 seconds to answer DemoClient.Connect(); int numberOfMailsInMailbox, mailboxSize; DemoClient.GetMailboxStats(out numberOfMailsInMailbox, out mailboxSize); //get at most the xx first emails RxMailMessage mm; int downloadNumberOfEmails; int maxDownloadEmails = 99; if (numberOfMailsInMailbox<maxDownloadEmails) { downloadNumberOfEmails = numberOfMailsInMailbox; } else { downloadNumberOfEmails = maxDownloadEmails; } for (int i = 1;i <= downloadNumberOfEmails;i++) { DemoClient.GetEmail(i, out mm); if (mm==null) { Console.WriteLine("Email " + i.ToString() + " cannot be displayed."); } else { //Console.WriteLine(mm.MailStructure()); Console.WriteLine(mm.Body); } } //close connection DemoClient.Disconnect(); Console.WriteLine(); Console.WriteLine("======== Press Enter to end program"); Console.ReadLine(); }
/// <summary> /// Process a MIME entity /// /// A MIME entity consists of header and body. /// Separator lines in the body might mark children MIME entities /// </summary> private MimeEntityReturnCode ProcessMimeEntity(RxMailMessage message, string parentBoundaryStart) { bool hasParentBoundary = parentBoundaryStart.Length > 0; string parentBoundaryEnd = parentBoundaryStart + "--"; 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 too ! message.SetContentTypeFields("text/plain; charset=us-ascii"); //get header //---------- 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 (!readMultiLine(out response)) { //POP3 server has not send any more lines callGetEmailWarning("incomplete MIME entity header received"); //empty this message while (readMultiLine(out response)) { } System.Diagnostics.Debugger.Break(); //didn't have a sample email to test this return(MimeEntityReturnCode.problem); } if (response.Length < 1) { //empty line found => end of header if (completeHeaderField != null) { ProcessHeaderField(message, completeHeaderField); } else { //there was only an empty header. } break; } //check if there is a parent boundary in the header (wrong format!) if (hasParentBoundary && parentBoundaryFound(response, parentBoundaryStart, parentBoundaryEnd, out boundaryMimeReturnCode)) { callGetEmailWarning("MIME entity header prematurely ended by parent boundary"); //empty this message while (readMultiLine(out response)) { } System.Diagnostics.Debugger.Break(); //didn't have a sample email to test this 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 (response[0] == ' ' || response[0] == '\t') { //continuation line found. if (completeHeaderField == null) { callGetEmailWarning("Email header starts with continuation line"); //empty this message while (readMultiLine(out response)) { } System.Diagnostics.Debugger.Break(); //didn't have a sample email to test this return(MimeEntityReturnCode.problem); } else { // append space, if needed, and continuation line if (completeHeaderField[completeHeaderField.Length - 1] != ' ') { //previous line did not end with a whitespace //need to replace CRLF with a ' ' completeHeaderField += ' ' + response.TrimStart(WhiteSpaceChars); } else { //previous line did end with a whitespace completeHeaderField += response.TrimStart(WhiteSpaceChars); } } } else { //a new header field line found if (completeHeaderField == null) { //very first field, just copy it and then check for continuation lines completeHeaderField = response; } else { //new header line found ProcessHeaderField(message, completeHeaderField); //save the beginning of the next line completeHeaderField = response; } } }//end while read header lines //process body //------------ MimeEntitySB.Length = 0; //empty StringBuilder. For speed reasons, reuse StringBuilder defined as member of class string BoundaryDelimiterLineStart = null; bool isBoundaryDefined = false; if (message.ContentType.Boundary != null) { 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 (readMultiLine(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(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 MimeEntitySB.Append(response + CRLF); } //a complete MIME body read //convert received US ASCII characters to .NET string (Unicode) string TransferEncodedMessage = MimeEntitySB.ToString(); bool isAttachmentSaved = false; switch (message.ContentTransferEncoding) { case TransferEncoding.SevenBit: //nothing to do if (message.MediaMainType == "message" && message.MediaSubType == "rfc822") { System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding(); using (MemoryStream mem = new MemoryStream(encoding.GetBytes(TransferEncodedMessage))) { Pop3MimeClient pop3Embedded = new Pop3MimeClient(mem); pop3Embedded.ProcessEmbedded(ref message); message.SetContentTypeFields("message/rfc822"); } } else { saveMessageBody(message, TransferEncodedMessage); } break; case TransferEncoding.Base64: //convert base 64 -> byte[] byte[] bodyBytes = System.Convert.FromBase64String(TransferEncodedMessage); message.ContentStream = new MemoryStream(bodyBytes, false); if (message.MediaMainType == "text") { //convert byte[] -> string message.Body = DecodeByteArryToString(bodyBytes, message.BodyEncoding); } else if (message.MediaMainType == "image" || message.MediaMainType == "application") { SaveAttachment(message); isAttachmentSaved = true; } break; case TransferEncoding.QuotedPrintable: saveMessageBody(message, QuotedPrintable.Decode(TransferEncodedMessage)); break; default: saveMessageBody(message, TransferEncodedMessage); //no need to raise a warning here, the warning was done when analising the header break; } if (message.ContentDisposition != null && message.ContentDisposition.DispositionType.ToLowerInvariant() == "attachment" && !isAttachmentSaved) { SaveAttachment(message); isAttachmentSaved = true; } return(boundaryMimeReturnCode); }
/// <summary> /// Process a MIME entity /// /// A MIME entity consists of header and body. /// Separator lines in the body might mark children MIME entities /// </summary> private MimeEntityReturnCode ProcessMimeEntity(RxMailMessage message, string parentBoundaryStart) { bool hasParentBoundary = parentBoundaryStart.Length>0; string parentBoundaryEnd = parentBoundaryStart + "--"; 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 too ! message.SetContentTypeFields("text/plain; charset=us-ascii"); //get header //---------- 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 (!readMultiLine(out response)) { //POP3 server has not send any more lines callGetEmailWarning("incomplete MIME entity header received"); //empty this message while (readMultiLine(out response)) { } System.Diagnostics.Debugger.Break(); //didn't have a sample email to test this return MimeEntityReturnCode.problem; } if (response.Length<1) { //empty line found => end of header if (completeHeaderField!=null) { ProcessHeaderField(message, completeHeaderField); }else{ //there was only an empty header. } break; } //check if there is a parent boundary in the header (wrong format!) if (hasParentBoundary && parentBoundaryFound(response, parentBoundaryStart, parentBoundaryEnd, out boundaryMimeReturnCode)){ callGetEmailWarning("MIME entity header prematurely ended by parent boundary"); //empty this message while (readMultiLine(out response)) { } System.Diagnostics.Debugger.Break(); //didn't have a sample email to test this 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 (response[0]==' ' || response[0]=='\t') { //continuation line found. if (completeHeaderField==null){ callGetEmailWarning("Email header starts with continuation line"); //empty this message while (readMultiLine(out response)) { } System.Diagnostics.Debugger.Break(); //didn't have a sample email to test this return MimeEntityReturnCode.problem; }else { // append space, if needed, and continuation line if (completeHeaderField[completeHeaderField.Length-1]!=' ') { //previous line did not end with a whitespace //need to replace CRLF with a ' ' completeHeaderField += ' ' + response.TrimStart(WhiteSpaceChars); } else { //previous line did end with a whitespace completeHeaderField += response.TrimStart(WhiteSpaceChars); } } } else { //a new header field line found if (completeHeaderField==null) { //very first field, just copy it and then check for continuation lines completeHeaderField = response; } else { //new header line found ProcessHeaderField(message, completeHeaderField); //save the beginning of the next line completeHeaderField = response; } } }//end while read header lines //process body //------------ MimeEntitySB.Length=0; //empty StringBuilder. For speed reasons, reuse StringBuilder defined as member of class string BoundaryDelimiterLineStart = null; bool isBoundaryDefined = false; if (message.ContentType.Boundary!=null) { 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 (readMultiLine(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 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 MimeEntitySB.Append(response + CRLF); } //a complete MIME body read //convert received US ASCII characters to .NET string (Unicode) string TransferEncodedMessage = MimeEntitySB.ToString(); bool isAttachmentSaved = false; switch (message.ContentTransferEncoding) { case TransferEncoding.SevenBit: //nothing to do if ( message.MediaMainType == "message" && message.MediaSubType == "rfc822" ) { System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding(); using ( MemoryStream mem = new MemoryStream(encoding.GetBytes(TransferEncodedMessage)) ) { Pop3MimeClient pop3Embedded = new Pop3MimeClient(mem); pop3Embedded.ProcessEmbedded(ref message); message.SetContentTypeFields("message/rfc822"); } } else { saveMessageBody(message, TransferEncodedMessage); } break; case TransferEncoding.Base64: //convert base 64 -> byte[] byte[] bodyBytes = System.Convert.FromBase64String(TransferEncodedMessage); message.ContentStream = new MemoryStream(bodyBytes, false); if (message.MediaMainType=="text") { //convert byte[] -> string message.Body = DecodeByteArryToString(bodyBytes, message.BodyEncoding); } else if (message.MediaMainType=="image" || message.MediaMainType=="application") { SaveAttachment(message); isAttachmentSaved = true; } break; case TransferEncoding.QuotedPrintable: saveMessageBody(message, QuotedPrintable.Decode(TransferEncodedMessage)); break; default: saveMessageBody(message, TransferEncodedMessage); //no need to raise a warning here, the warning was done when analising the header break; } if (message.ContentDisposition!=null && message.ContentDisposition.DispositionType.ToLowerInvariant()=="attachment" && !isAttachmentSaved) { SaveAttachment(message); isAttachmentSaved = true; } return boundaryMimeReturnCode; }