📄 pop3mailclient.cs
字号:
// POP3 Client
// ===========
//
// copyright by Peter Huber, Singapore, 2006
// this code is provided as is, bugs are probable, free for any use at own risk, no
// responsibility accepted. All rights, title and interest in and to the accompanying content retained. :-)
//
// based on POP3 Client as a C# Class, by Bill Dean, http://www.codeproject.com/csharp/Pop3MailClient.asp
// based on Retrieve Mail From a POP3 Server Using C#, by Agus Kurniawan, http://www.codeproject.com/csharp/popapp.asp
// based on Post Office Protocol - Version 3, http://www.ietf.org/rfc/rfc1939.txt
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Net.Security;
using System.Text;
namespace Mail {
// Supporting classes and structs
// ==============================
/// <summary>
/// Combines Email ID with Email UID for one email
/// The POP3 server assigns to each message a unique Email UID, which will not change for the life time
/// of the message and no other message should use the same.
///
/// Exceptions:
/// Throws Pop3Exception if there is a serious communication problem with the POP3 server, otherwise
///
/// </summary>
public struct EmailUid {
/// <summary>
/// used in POP3 commands to indicate which message (only valid in the present session)
/// </summary>
public int EmailId;
/// <summary>
/// Uid is always the same for a message, regardless of session
/// </summary>
public string Uid;
/// <summary>
/// constructor
/// </summary>
public EmailUid(int EmailId, string Uid) {
this.EmailId = EmailId;
this.Uid = Uid;
}
}
/// <summary>
/// If anything goes wrong within Pop3MailClient, a Pop3Exception is raised
/// </summary>
public class Pop3Exception:ApplicationException {
/// <summary>
/// Pop3 exception with no further explanation
/// </summary>
public Pop3Exception() { }
/// <summary>
/// Pop3 exception with further explanation
/// </summary>
public Pop3Exception(string ErrorMessage) : base(ErrorMessage) { }
}
/// <summary>
/// A pop 3 connection goes through the following states:
/// </summary>
public enum Pop3ConnectionStateEnum {
/// <summary>
/// undefined
/// </summary>
None=0,
/// <summary>
/// not connected yet to POP3 server
/// </summary>
Disconnected,
/// <summary>
/// TCP connection has been opened and the POP3 server has sent the greeting. POP3 server expects user name and password
/// </summary>
Authorization,
/// <summary>
/// client has identified itself successfully with the POP3, server has locked all messages
/// </summary>
Connected,
/// <summary>
/// QUIT command was sent, the server has deleted messages marked for deletion and released the resources
/// </summary>
Closed
}
// Delegates for Pop3MailClient
// ============================
/// <summary>
/// If POP3 Server doesn't react as expected or this code has a problem, but
/// can continue with the execution, a Warning is called.
/// </summary>
/// <param name="WarningText"></param>
/// <param name="Response">string received from POP3 server</param>
public delegate void WarningHandler(string WarningText, string Response);
/// <summary>
/// Traces all the information exchanged between POP3 client and POP3 server plus some
/// status messages from POP3 client.
/// Helpful to investigate any problem.
/// Console.WriteLine() can be used
/// </summary>
public delegate void TraceHandler(string TraceText);
// Pop3MailClient Class
// ====================
/// <summary>
/// provides access to emails on a POP3 Server
/// </summary>
public class Pop3MailClient {
//Events
//------
/// <summary>
/// Called whenever POP3 server doesn't react as expected, but no runtime error is thrown.
/// </summary>
public event WarningHandler Warning;
/// <summary>
/// call warning event
/// </summary>
/// <param name="methodName">name of the method where warning is needed</param>
/// <param name="response">answer from POP3 server causing the warning</param>
/// <param name="warningText">explanation what went wrong</param>
/// <param name="warningParameters"></param>
protected void CallWarning(string methodName, string response, string warningText, params object[] warningParameters) {
try {
warningText = string.Format(warningText, warningParameters);
} catch {
}
if (Warning!=null) {
Warning(methodName + ": " + warningText, response);
}
CallTrace("!! {0}", warningText);
}
/// <summary>
/// Shows the communication between PopClient and PopServer, including warnings
/// </summary>
public event TraceHandler Trace;
/// <summary>
/// call Trace event
/// </summary>
/// <param name="text">string to be traced</param>
/// <param name="parameters"></param>
protected void CallTrace(string text, params object[] parameters) {
if (Trace!=null) {
Trace(DateTime.Now.ToString("hh:mm:ss ") + popServer + " " + string.Format(text, parameters));
}
}
/// <summary>
/// Trace information received from POP3 server
/// </summary>
/// <param name="text">string to be traced</param>
/// <param name="parameters"></param>
protected void TraceFrom(string text, params object[] parameters) {
if (Trace!=null) {
CallTrace(" " + string.Format(text, parameters));
}
}
//Properties
//----------
/// <summary>
/// Get POP3 server name
/// </summary>
public string PopServer {
get { return popServer; }
}
/// <summary>
/// POP3 server name
/// </summary>
protected string popServer;
/// <summary>
/// Get POP3 server port
/// </summary>
public int Port {
get { return port; }
}
/// <summary>
/// POP3 server port
/// </summary>
protected int port;
/// <summary>
/// Should SSL be used for connection with POP3 server ?
/// </summary>
public bool UseSSL {
get { return useSSL; }
}
/// <summary>
/// Should SSL be used for connection with POP3 server ?
/// </summary>
private bool useSSL;
/// <summary>
/// should Pop3MailClient automatically reconnect if POP3 server has dropped the
/// connection due to a timeout ?
/// </summary>
public bool IsAutoReconnect {
get { return isAutoReconnect; }
set { isAutoReconnect = value; }
}
private bool isAutoReconnect = false;
//timeout has occurred, we try to perform an autoreconnect
private bool isTimeoutReconnect = false;
/// <summary>
/// Get / set read timeout (miliseconds)
/// </summary>
public int ReadTimeout {
get { return readTimeout; }
set {
readTimeout = value;
if (pop3Stream!=null && pop3Stream.CanTimeout) {
pop3Stream.ReadTimeout = readTimeout;
}
}
}
/// <summary>
/// POP3 server read timeout
/// </summary>
protected int readTimeout = -1;
/// <summary>
/// Get owner name of mailbox on POP3 server
/// </summary>
public string Username {
get { return username; }
}
/// <summary>
/// Owner name of mailbox on POP3 server
/// </summary>
protected string username;
/// <summary>
/// Get password for mailbox on POP3 server
/// </summary>
public string Password {
get { return password; }
}
/// <summary>
/// Password for mailbox on POP3 server
/// </summary>
protected string password;
/// <summary>
/// Get connection status with POP3 server
/// </summary>
public Pop3ConnectionStateEnum Pop3ConnectionState {
get { return pop3ConnectionState; }
}
/// <summary>
/// connection status with POP3 server
/// </summary>
protected Pop3ConnectionStateEnum pop3ConnectionState = Pop3ConnectionStateEnum.Disconnected;
// Methods
// -------
/// <summary>
/// set POP3 connection state
/// </summary>
protected void setPop3ConnectionState(Pop3ConnectionStateEnum State) {
pop3ConnectionState = State;
CallTrace(" Pop3MailClient Connection State {0} reached", State);
}
/// <summary>
/// throw exception if POP3 connection is not in the required state
/// </summary>
protected void EnsureState(Pop3ConnectionStateEnum requiredState) {
if (pop3ConnectionState!=requiredState) {
// wrong connection state
throw new Pop3Exception("GetMailboxStats only accepted during connection state: " + requiredState.ToString() +
"\n The connection to server "+ popServer + " is in state " + pop3ConnectionState.ToString());
}
}
//private fields
//--------------
/// <summary>
/// TCP to POP3 server
/// </summary>
private TcpClient serverTcpConnection;
/// <summary>
/// Stream from POP3 server with or without SSL
/// </summary>
private Stream pop3Stream;
/// <summary>
/// Reader for POP3 message
/// </summary>
protected StreamReader pop3StreamReader;
/// <summary>
/// char 'array' for carriage return / line feed
/// </summary>
protected string CRLF = "\r\n";
//public methods
//--------------
/// <summary>
/// Make POP3 client ready to connect to POP3 server
/// </summary>
/// <param name="PopServer"><example>pop.gmail.com</example></param>
/// <param name="Port"><example>995</example></param>
/// <param name="useSSL">True: SSL is used for connection to POP3 server</param>
/// <param name="Username"><example>abc@gmail.com</example></param>
/// <param name="Password">Secret</param>
public Pop3MailClient(string PopServer, int Port, bool useSSL, string Username, string Password) {
this.popServer = PopServer;
this.port = Port;
this.useSSL = useSSL;
this.username = Username;
this.password = Password;
}
/// <summary>
/// Connect to POP3 server
/// </summary>
public void Connect() {
if (pop3ConnectionState!=Pop3ConnectionStateEnum.Disconnected &&
pop3ConnectionState!=Pop3ConnectionStateEnum.Closed &&
!isTimeoutReconnect) {
CallWarning("connect", "", "Connect command received, but connection state is: " + pop3ConnectionState.ToString());
} else {
//establish TCP connection
try {
CallTrace(" Connect at port {0}", port);
serverTcpConnection = new TcpClient(popServer, port);
} catch (Exception ex) {
throw new Pop3Exception("Connection to server "+ popServer + ", port " + port + " failed.\nRuntime Error: "+ex.ToString());
}
if (useSSL) {
//get SSL stream
try {
CallTrace(" Get SSL connection");
pop3Stream = new SslStream(serverTcpConnection.GetStream(), false);
pop3Stream.ReadTimeout = readTimeout;
} catch (Exception ex) {
throw new Pop3Exception("Server " + popServer + " found, but cannot get SSL data stream.\nRuntime Error: "+ex.ToString());
}
//perform SSL authentication
try {
CallTrace(" Get SSL authentication");
((SslStream)pop3Stream).AuthenticateAsClient(popServer);
} catch (Exception ex) {
throw new Pop3Exception("Server " + popServer + " found, but problem with SSL Authentication.\nRuntime Error: " + ex.ToString());
}
} else {
//create a stream to POP3 server without using SSL
try {
CallTrace(" Get connection without SSL");
pop3Stream = serverTcpConnection.GetStream();
pop3Stream.ReadTimeout = readTimeout;
} catch (Exception ex) {
throw new Pop3Exception("Server " + popServer + " found, but cannot get data stream (without SSL).\nRuntime Error: "+ex.ToString());
}
}
//get stream for reading from pop server
//POP3 allows only US-ASCII. The message will be translated in the proper encoding in a later step
try {
pop3StreamReader= new StreamReader(pop3Stream, Encoding.ASCII);
} catch (Exception ex) {
if (useSSL) {
throw new Pop3Exception("Server " + popServer + " found, but cannot read from SSL stream.\nRuntime Error: " + ex.ToString());
} else {
throw new Pop3Exception("Server " + popServer + " found, but cannot read from stream (without SSL).\nRuntime Error: " + ex.ToString());
}
}
//ready for authorisation
string response;
if (!readSingleLine(out response)) {
throw new Pop3Exception("Server " + popServer + " not ready to start AUTHORIZATION.\nMessage: " + response);
}
setPop3ConnectionState(Pop3ConnectionStateEnum.Authorization);
//send user name
if (!executeCommand("USER "+ username, out response)) {
throw new Pop3Exception("Server " + popServer + " doesn't accept username '" + username + "'.\nMessage: " + response);
}
//send password
if (!executeCommand("PASS " + password, out response)) {
throw new Pop3Exception("Server " + popServer + " doesn't accept password '" + password + "' for user '" + username + "'.\nMessage: " + response);
}
setPop3ConnectionState(Pop3ConnectionStateEnum.Connected);
}
}
/// <summary>
/// Disconnect from POP3 Server
/// </summary>
public void Disconnect() {
if (pop3ConnectionState==Pop3ConnectionStateEnum.Disconnected ||
pop3ConnectionState==Pop3ConnectionStateEnum.Closed) {
CallWarning("disconnect", "", "Disconnect received, but was already disconnected.");
} else {
//ask server to end session and possibly to remove emails marked for deletion
try {
string response;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -