📄 inetmail.cxx
字号:
}
PString fromDomain;
PINDEX extendedArgPos = ParseMailPath(sender, "from", fromAddress, fromDomain, fromPath);
if (extendedArgPos == 0 || fromAddress.IsEmpty()) {
WriteResponse(501, "Syntax error.");
return;
}
fromAddress += fromDomain;
if (extendedHello) {
PINDEX equalPos = sender.Find('=', extendedArgPos);
PCaselessString body = sender(extendedArgPos, equalPos).Trim();
PCaselessString mime = sender.Mid(equalPos+1).Trim();
eightBitMIME = (body == "BODY" && mime == "8BITMIME");
}
PString response = "Sender " + fromAddress;
if (eightBitMIME)
response += " and 8BITMIME";
WriteResponse(250, response + " Ok");
}
void PSMTPServer::OnDATA()
{
if (fromAddress.IsEmpty()) {
WriteResponse(503, "Need a valid MAIL command.");
return;
}
if (toNames.GetSize() == 0) {
WriteResponse(503, "Need a valid RCPT command.");
return;
}
// Ok, everything is ready to start the message.
if (!WriteResponse(354,
eightBitMIME ? "Enter 8BITMIME message, terminate with '<CR><LF>.<CR><LF>'."
: "Enter mail, terminate with '.' alone on a line."))
return;
endMIMEDetectState = eightBitMIME ? StuffIdle : DontStuff;
BOOL ok = TRUE;
BOOL completed = FALSE;
BOOL starting = TRUE;
while (ok && !completed) {
PCharArray buffer;
if (eightBitMIME)
ok = OnMIMEData(buffer, completed);
else
ok = OnTextData(buffer, completed);
if (ok) {
ok = HandleMessage(buffer, starting, completed);
starting = FALSE;
}
}
if (ok)
WriteResponse(250, "Message received Ok.");
else
WriteResponse(554, "Message storage failed.");
}
BOOL PSMTPServer::OnUnknown(const PCaselessString & command)
{
WriteResponse(500, "Command \"" + command + "\" unrecognised.");
return TRUE;
}
BOOL PSMTPServer::OnTextData(PCharArray & buffer, BOOL & completed)
{
PString line;
while (ReadLine(line)) {
PINDEX len = line.GetLength();
if (len == 1 && line[0] == '.') {
completed = TRUE;
return TRUE;
}
PINDEX start = (len > 1 && line[0] == '.' && line[1] == '.') ? 1 : 0;
PINDEX size = buffer.GetSize();
len -= start;
memcpy(buffer.GetPointer(size + len + 2) + size,
((const char *)line)+start, len);
size += len;
buffer[size++] = '\r';
buffer[size++] = '\n';
if (size > messageBufferSize)
return TRUE;
}
return FALSE;
}
BOOL PSMTPServer::OnMIMEData(PCharArray & buffer, BOOL & completed)
{
PINDEX count = 0;
int c;
while ((c = ReadChar()) >= 0) {
if (count >= buffer.GetSize())
buffer.SetSize(count + 100);
switch (endMIMEDetectState) {
case StuffIdle :
buffer[count++] = (char)c;
break;
case StuffCR :
endMIMEDetectState = c != '\n' ? StuffIdle : StuffCRLF;
buffer[count++] = (char)c;
break;
case StuffCRLF :
if (c == '.')
endMIMEDetectState = StuffCRLFdot;
else {
endMIMEDetectState = StuffIdle;
buffer[count++] = (char)c;
}
break;
case StuffCRLFdot :
switch (c) {
case '\r' :
endMIMEDetectState = StuffCRLFdotCR;
break;
case '.' :
endMIMEDetectState = StuffIdle;
buffer[count++] = (char)c;
break;
default :
endMIMEDetectState = StuffIdle;
buffer[count++] = '.';
buffer[count++] = (char)c;
}
break;
case StuffCRLFdotCR :
if (c == '\n') {
completed = TRUE;
return TRUE;
}
buffer[count++] = '.';
buffer[count++] = '\r';
buffer[count++] = (char)c;
endMIMEDetectState = StuffIdle;
default :
PAssertAlways("Illegal SMTP state");
}
if (count > messageBufferSize) {
buffer.SetSize(messageBufferSize);
return TRUE;
}
}
return FALSE;
}
PSMTPServer::ForwardResult PSMTPServer::ForwardDomain(PCaselessString & userDomain,
PCaselessString & forwardDomainList)
{
return userDomain.IsEmpty() && forwardDomainList.IsEmpty() ? LocalDomain : CannotForward;
}
PSMTPServer::LookUpResult PSMTPServer::LookUpName(const PCaselessString &,
PString & expandedName)
{
expandedName = PString();
return LookUpError;
}
BOOL PSMTPServer::HandleMessage(PCharArray &, BOOL, BOOL)
{
return FALSE;
}
//////////////////////////////////////////////////////////////////////////////
// PPOP3
static char const * const POP3Commands[PPOP3::NumCommands] = {
"USER", "PASS", "QUIT", "RSET", "NOOP", "STAT",
"LIST", "RETR", "DELE", "APOP", "TOP", "UIDL"
};
PString PPOP3::okResponse = "+OK";
PString PPOP3::errResponse = "-ERR";
PPOP3::PPOP3()
: PInternetProtocol("pop3 110", NumCommands, POP3Commands)
{
}
PINDEX PPOP3::ParseResponse(const PString & line)
{
lastResponseCode = line[0] == '+';
PINDEX endCode = line.Find(' ');
if (endCode != P_MAX_INDEX)
lastResponseInfo = line.Mid(endCode+1);
else
lastResponseInfo = PString();
return 0;
}
//////////////////////////////////////////////////////////////////////////////
// PPOP3Client
PPOP3Client::PPOP3Client()
{
loggedIn = FALSE;
}
PPOP3Client::~PPOP3Client()
{
Close();
}
BOOL PPOP3Client::OnOpen()
{
return ReadResponse() && lastResponseCode > 0;
}
BOOL PPOP3Client::Close()
{
BOOL ok = TRUE;
if (IsOpen() && loggedIn) {
SetReadTimeout(60000);
ok = ExecuteCommand(QUIT, "") > 0;
}
return PInternetProtocol::Close() && ok;
}
BOOL PPOP3Client::LogIn(const PString & username, const PString & password)
{
if (ExecuteCommand(USER, username) <= 0)
return FALSE;
if (ExecuteCommand(PASS, password) <= 0)
return FALSE;
loggedIn = TRUE;
return TRUE;
}
int PPOP3Client::GetMessageCount()
{
if (ExecuteCommand(STAT, "") <= 0)
return -1;
return (int)lastResponseInfo.AsInteger();
}
PUnsignedArray PPOP3Client::GetMessageSizes()
{
PUnsignedArray sizes;
if (ExecuteCommand(LIST, "") > 0) {
PString msgInfo;
while (ReadLine(msgInfo))
sizes.SetAt((PINDEX)msgInfo.AsInteger()-1,
(unsigned)msgInfo.Mid(msgInfo.Find(' ')).AsInteger());
}
return sizes;
}
PStringArray PPOP3Client::GetMessageHeaders()
{
PStringArray headers;
int count = GetMessageCount();
for (int msgNum = 1; msgNum <= count; msgNum++) {
if (ExecuteCommand(TOP, PString(PString::Unsigned,msgNum) + " 0") > 0) {
PString headerLine;
while (ReadLine(headerLine, TRUE))
headers[msgNum-1] += headerLine;
}
}
return headers;
}
BOOL PPOP3Client::BeginMessage(PINDEX messageNumber)
{
return ExecuteCommand(RETR, PString(PString::Unsigned, messageNumber)) > 0;
}
BOOL PPOP3Client::DeleteMessage(PINDEX messageNumber)
{
return ExecuteCommand(DELE, PString(PString::Unsigned, messageNumber)) > 0;
}
//////////////////////////////////////////////////////////////////////////////
// PPOP3Server
PPOP3Server::PPOP3Server()
{
}
BOOL PPOP3Server::OnOpen()
{
return WriteResponse(okResponse, PIPSocket::GetHostName() +
" POP3 server ready at " +
PTime(PTime::MediumDateTime).AsString());
}
BOOL PPOP3Server::ProcessCommand()
{
PString args;
PINDEX num;
if (!ReadCommand(num, args))
return FALSE;
switch (num) {
case USER :
OnUSER(args);
break;
case PASS :
OnPASS(args);
break;
case QUIT :
OnQUIT();
return FALSE;
case RSET :
OnRSET();
break;
case NOOP :
OnNOOP();
break;
case STAT :
OnSTAT();
break;
case LIST :
OnLIST((PINDEX)args.AsInteger());
break;
case RETR :
OnRETR((PINDEX)args.AsInteger());
break;
case DELE :
OnDELE((PINDEX)args.AsInteger());
break;
case TOP :
if (args.Find(' ') == P_MAX_INDEX)
WriteResponse(errResponse, "Syntax error");
else
OnTOP((PINDEX)args.AsInteger(),
(PINDEX)args.Mid(args.Find(' ')).AsInteger());
break;
case UIDL :
OnUIDL((PINDEX)args.AsInteger());
break;
default :
return OnUnknown(args);
}
return TRUE;
}
void PPOP3Server::OnUSER(const PString & name)
{
messageSizes.SetSize(0);
messageIDs.SetSize(0);
username = name;
WriteResponse(okResponse, "User name accepted.");
}
void PPOP3Server::OnPASS(const PString & password)
{
if (username.IsEmpty())
WriteResponse(errResponse, "No user name specified.");
else if (HandleOpenMailbox(username, password))
WriteResponse(okResponse, username + " mail is available.");
else
WriteResponse(errResponse, "No access to " + username + " mail.");
messageDeletions.SetSize(messageIDs.GetSize());
}
void PPOP3Server::OnQUIT()
{
for (PINDEX i = 0; i < messageDeletions.GetSize(); i++)
if (messageDeletions[i])
HandleDeleteMessage(i+1, messageIDs[i]);
WriteResponse(okResponse, PIPSocket::GetHostName() +
" POP3 server signing off at " +
PTime(PTime::MediumDateTime).AsString());
Close();
}
void PPOP3Server::OnRSET()
{
for (PINDEX i = 0; i < messageDeletions.GetSize(); i++)
messageDeletions[i] = FALSE;
WriteResponse(okResponse, "Resetting state.");
}
void PPOP3Server::OnNOOP()
{
WriteResponse(okResponse, "Doing nothing.");
}
void PPOP3Server::OnSTAT()
{
DWORD total = 0;
for (PINDEX i = 0; i < messageSizes.GetSize(); i++)
total += messageSizes[i];
WriteResponse(okResponse, psprintf("%u %u", messageSizes.GetSize(), total));
}
void PPOP3Server::OnLIST(PINDEX msg)
{
if (msg == 0) {
WriteResponse(okResponse, psprintf("%u messages.", messageSizes.GetSize()));
for (PINDEX i = 0; i < messageSizes.GetSize(); i++)
if (!messageDeletions[i])
WriteLine(psprintf("%u %u", i+1, messageSizes[i]));
WriteLine(".");
}
else if (msg < 1 || msg > messageSizes.GetSize())
WriteResponse(errResponse, "No such message.");
else
WriteResponse(okResponse, psprintf("%u %u", msg, messageSizes[msg-1]));
}
void PPOP3Server::OnRETR(PINDEX msg)
{
if (msg < 1 || msg > messageDeletions.GetSize())
WriteResponse(errResponse, "No such message.");
else {
WriteResponse(okResponse,
PString(PString::Unsigned, messageSizes[msg-1]) + " octets.");
stuffingState = StuffIdle;
HandleSendMessage(msg, messageIDs[msg-1], P_MAX_INDEX);
stuffingState = DontStuff;
WriteString(CRLFdotCRLF);
}
}
void PPOP3Server::OnDELE(PINDEX msg)
{
if (msg < 1 || msg > messageDeletions.GetSize())
WriteResponse(errResponse, "No such message.");
else {
messageDeletions[msg-1] = TRUE;
WriteResponse(okResponse, "Message marked for deletion.");
}
}
void PPOP3Server::OnTOP(PINDEX msg, PINDEX count)
{
if (msg < 1 || msg > messageDeletions.GetSize())
WriteResponse(errResponse, "No such message.");
else {
WriteResponse(okResponse, "Top of message");
stuffingState = StuffIdle;
HandleSendMessage(msg, messageIDs[msg-1], count);
stuffingState = DontStuff;
WriteString(CRLFdotCRLF);
}
}
void PPOP3Server::OnUIDL(PINDEX msg)
{
if (msg == 0) {
WriteResponse(okResponse,
PString(PString::Unsigned, messageIDs.GetSize()) + " messages.");
for (PINDEX i = 0; i < messageIDs.GetSize(); i++)
if (!messageDeletions[i])
WriteLine(PString(PString::Unsigned, i+1) & messageIDs[i]);
WriteLine(".");
}
else if (msg < 1 || msg > messageSizes.GetSize())
WriteResponse(errResponse, "No such message.");
else
WriteLine(PString(PString::Unsigned, msg) & messageIDs[msg-1]);
}
BOOL PPOP3Server::OnUnknown(const PCaselessString & command)
{
WriteResponse(errResponse, "Command \"" + command + "\" unrecognised.");
return TRUE;
}
BOOL PPOP3Server::HandleOpenMailbox(const PString &, const PString &)
{
return FALSE;
}
void PPOP3Server::HandleSendMessage(PINDEX, const PString &, PINDEX)
{
}
void PPOP3Server::HandleDeleteMessage(PINDEX, const PString &)
{
}
// End Of File ///////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -