⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 inetmail.cxx

📁 pwlib源码库
💻 CXX
📖 第 1 页 / 共 3 页
字号:
/* * inetmail.cxx * * Internet Mail classes. * * Portable Windows Library * * Copyright (c) 1993-2002 Equivalence Pty. Ltd. * * The contents of this file are subject to the Mozilla Public License * Version 1.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. * * The Original Code is Portable Windows Library. * * The Initial Developer of the Original Code is Equivalence Pty. Ltd. * * Contributor(s): Federico Pinna and Reitek S.p.A. (SASL authentication) * * $Log: inetmail.cxx,v $ * Revision 1.30  2004/05/09 07:23:49  rjongbloed * More work on XMPP, thanks Federico Pinna and Reitek S.p.A. * * Revision 1.29  2004/05/02 08:58:15  csoutheren * Removed warnings when compling without SASL * * Revision 1.28  2004/04/28 11:26:43  csoutheren * Hopefully fixed SASL and SASL2 problems * * Revision 1.27  2004/04/26 01:33:20  rjongbloed * Fixed minor problem with SASL authentication, thanks Federico Pinna, Reitek S.p.A. * * Revision 1.26  2004/04/21 00:29:56  csoutheren * Added SASL authentication to PPOP3Client and PSMTPClient * Thanks to Federico Pinna and Reitek S.p.A. * * Revision 1.25  2004/04/03 06:54:25  rjongbloed * Many and various changes to support new Visual C++ 2003 * * Revision 1.24  2003/02/20 00:16:06  craigs * Changed MIME_Version to MIME-Version * * Revision 1.23  2002/12/19 01:35:24  robertj * Fixed problem with returning incorrect lastWriteLength on translated output. * * Revision 1.22  2002/11/06 22:47:25  robertj * Fixed header comment (copyright etc) * * Revision 1.21  2002/01/07 05:26:47  robertj * Fixed getting scan list of messages, thanks xradish * * Revision 1.20  2001/09/28 00:45:27  robertj * Removed HasKey() as is confusing due to ancestor Contains(). * * Revision 1.19  2000/11/21 01:49:25  robertj * Fixed warning on GNU compiler. * * Revision 1.18  2000/11/16 07:15:15  robertj * Fixed problem with not closing off base64 encoding at next MIME part. * * Revision 1.17  2000/11/14 08:30:03  robertj * Fixed bug in closing SMTP client, conditional around wrong way. * * Revision 1.16  2000/11/10 01:08:11  robertj * Added content transfer encoding and automatic base64 translation. * * Revision 1.15  2000/11/09 06:01:58  robertj * Added MIME version and content disposition to RFC822 class. * * Revision 1.14  2000/11/09 05:50:23  robertj * Added RFC822 aware channel class for doing internet mail. * * Revision 1.13  2000/06/21 01:01:22  robertj * AIX port, thanks Wolfgang Platzer (wolfgang.platzer@infonova.at). * * Revision 1.12  1998/11/30 04:52:01  robertj * New directory structure * * Revision 1.11  1998/09/23 06:22:18  robertj * Added open source copyright license. * * Revision 1.10  1998/01/26 02:49:20  robertj * GNU support. * * Revision 1.9  1997/07/14 11:47:14  robertj * Added "const" to numerous variables. * * Revision 1.8  1996/12/21 01:24:39  robertj * Added missing open message to smtp server. * * Revision 1.7  1996/09/14 13:18:03  robertj * Renamed file and changed to be a protocol off new indirect channel to separate *   the protocol from the low level byte transport channel. * * Revision 1.6  1996/07/27 04:12:45  robertj * Redesign and reimplement of mail sockets. * * Revision 1.5  1996/06/28 13:22:09  robertj * Changed SMTP incoming message handler so can tell when started, processing or ended message. * * Revision 1.4  1996/05/26 03:46:51  robertj * Compatibility to GNU 2.7.x * * Revision 1.3  1996/03/18 13:33:16  robertj * Fixed incompatibilities to GNU compiler where PINDEX != int. * * Revision 1.2  1996/03/16 04:51:28  robertj * Changed lastResponseCode to an integer. * Added ParseReponse() for splitting reponse line into code and info. * * Revision 1.1  1996/03/04 12:12:51  robertj * Initial revision * */#ifdef __GNUC__#pragma implementation "inetmail.h"#endif#include <ptlib.h>#include <ptlib/sockets.h>#include <ptclib/inetmail.h>#if P_SASL2#include <ptclib/psasl.h>#endifstatic const PString CRLF = "\r\n";static const PString CRLFdotCRLF = "\r\n.\r\n";//////////////////////////////////////////////////////////////////////////////// PSMTPstatic char const * const SMTPCommands[PSMTP::NumCommands] = {  "HELO", "EHLO", "QUIT", "HELP", "NOOP",  "TURN", "RSET", "VRFY", "EXPN", "RCPT",  "MAIL", "SEND", "SAML", "SOML", "DATA",  "AUTH"};PSMTP::PSMTP()  : PInternetProtocol("smtp 25", NumCommands, SMTPCommands){}//////////////////////////////////////////////////////////////////////////////// PSMTPClientPSMTPClient::PSMTPClient(){  haveHello = FALSE;  extendedHello = FALSE;  eightBitMIME = FALSE;}PSMTPClient::~PSMTPClient(){  Close();}BOOL PSMTPClient::OnOpen(){  return ReadResponse() && lastResponseCode/100 == 2;}BOOL PSMTPClient::Close(){  BOOL ok = TRUE;  if (sendingData)    ok = EndMessage();  if (IsOpen() && haveHello) {    SetReadTimeout(60000);    ok = ExecuteCommand(QUIT, "")/100 == 2 && ok;  }  return PInternetProtocol::Close() && ok;}#if P_SASL2BOOL PSMTPClient::LogIn(const PString & username,                        const PString & password){  PString localHost;  PIPSocket * socket = GetSocket();  if (socket != NULL) {    localHost = socket->GetLocalHostName();  }  if (haveHello)    return FALSE; // Wrong state  if (ExecuteCommand(EHLO, localHost)/100 != 2)    return TRUE; // EHLO not supported, therefore AUTH not supported  haveHello = extendedHello = TRUE;  PStringArray caps = lastResponseInfo.Lines();  PStringArray serverMechs;  PINDEX i, max;  for (i = 0, max = caps.GetSize() ; i < max ; i++)    if (caps[i].Left(5) == "AUTH ") {      serverMechs = caps[i].Mid(5).Tokenise(" ", FALSE);      break;    }  if (serverMechs.GetSize() == 0)    return TRUE; // No mechanisms, no login  PSASLClient auth("smtp", username, username, password);  PStringSet ourMechs;  if (!auth.Init("", ourMechs))    return FALSE;  PString mech;  for (i = 0, max = serverMechs.GetSize() ; i < max ; i++)    if (ourMechs.Contains(serverMechs[i])) {      mech = serverMechs[i];      break;    }  if (mech.IsEmpty())    return TRUE;  // No mechanism in common  PString output;  // Ok, let's go...  if (!auth.Start(mech, output))    return FALSE;  if (!output.IsEmpty())    mech = mech + " " + output;  if (ExecuteCommand(AUTH, mech) <= 0)    return FALSE;  PSASLClient::PSASLResult result;  int response;  do {    response = lastResponseCode/100;    if (response == 2)      break;    else if (response != 3)      return FALSE;    result = auth.Negotiate(lastResponseInfo, output);          if (result == PSASLClient::Fail)      return FALSE;    if (!output.IsEmpty()) {      WriteLine(output);      if (!ReadResponse())        return FALSE;    }  } while (result == PSASLClient::Continue);  auth.End();  return TRUE;}#elseBOOL PSMTPClient::LogIn(const PString &,                        const PString &){  return TRUE;}#endifBOOL PSMTPClient::BeginMessage(const PString & from,                               const PString & to,                               BOOL useEightBitMIME){  fromAddress = from;  toNames.RemoveAll();  toNames.AppendString(to);  eightBitMIME = useEightBitMIME;  return _BeginMessage();}BOOL PSMTPClient::BeginMessage(const PString & from,                               const PStringList & toList,                               BOOL useEightBitMIME){  fromAddress = from;  toNames = toList;  eightBitMIME = useEightBitMIME;  return _BeginMessage();}BOOL PSMTPClient::_BeginMessage(){  PString localHost;  PString peerHost;  PIPSocket * socket = GetSocket();  if (socket != NULL) {    localHost = socket->GetLocalHostName();    peerHost = socket->GetPeerHostName();  }  if (!haveHello) {    if (ExecuteCommand(EHLO, localHost)/100 == 2)      haveHello = extendedHello = TRUE;  }  if (!haveHello) {    extendedHello = FALSE;    if (eightBitMIME)      return FALSE;    if (ExecuteCommand(HELO, localHost)/100 != 2)      return FALSE;    haveHello = TRUE;  }  if (fromAddress[0] != '"' && fromAddress.Find(' ') != P_MAX_INDEX)    fromAddress = '"' + fromAddress + '"';  if (!localHost && fromAddress.Find('@') == P_MAX_INDEX)    fromAddress += '@' + localHost;  if (ExecuteCommand(MAIL, "FROM:<" + fromAddress + '>')/100 != 2)    return FALSE;  for (PINDEX i = 0; i < toNames.GetSize(); i++) {    if (!peerHost && toNames[i].Find('@') == P_MAX_INDEX)      toNames[i] += '@' + peerHost;    if (ExecuteCommand(RCPT, "TO:<" + toNames[i] + '>')/100 != 2)      return FALSE;  }  if (ExecuteCommand(DATA, PString())/100 != 3)    return FALSE;  stuffingState = StuffIdle;  sendingData = TRUE;  return TRUE;}BOOL PSMTPClient::EndMessage(){  flush();  stuffingState = DontStuff;  sendingData = FALSE;  if (!WriteString(CRLFdotCRLF))    return FALSE;  return ReadResponse() && lastResponseCode/100 == 2;}//////////////////////////////////////////////////////////////////////////////// PSMTPServerPSMTPServer::PSMTPServer(){  extendedHello = FALSE;  eightBitMIME = FALSE;  messageBufferSize = 30000;  ServerReset();}void PSMTPServer::ServerReset(){  eightBitMIME = FALSE;  sendCommand = WasMAIL;  fromAddress = PString();  toNames.RemoveAll();}BOOL PSMTPServer::OnOpen(){  return WriteResponse(220, PIPSocket::GetHostName() + "ESMTP server ready");}BOOL PSMTPServer::ProcessCommand(){  PString args;  PINDEX num;  if (!ReadCommand(num, args))    return FALSE;  switch (num) {    case HELO :      OnHELO(args);      break;    case EHLO :      OnEHLO(args);      break;    case QUIT :      OnQUIT();      return FALSE;    case NOOP :      OnNOOP();      break;    case TURN :      OnTURN();      break;    case RSET :      OnRSET();      break;    case VRFY :      OnVRFY(args);      break;    case EXPN :      OnEXPN(args);      break;    case RCPT :      OnRCPT(args);      break;    case MAIL :      OnMAIL(args);      break;    case SEND :      OnSEND(args);      break;    case SAML :      OnSAML(args);      break;    case SOML :      OnSOML(args);      break;    case DATA :      OnDATA();      break;    default :      return OnUnknown(args);  }  return TRUE;}void PSMTPServer::OnHELO(const PCaselessString & remoteHost){  extendedHello = FALSE;  ServerReset();  PCaselessString peerHost;  PIPSocket * socket = GetSocket();  if (socket != NULL)    peerHost = socket->GetPeerHostName();  PString response = PIPSocket::GetHostName() & "Hello" & peerHost + ", ";  if (remoteHost == peerHost)    response += "pleased to meet you.";  else if (remoteHost.IsEmpty())    response += "why do you wish to remain anonymous?";  else    response += "why do you wish to call yourself \"" + remoteHost + "\"?";  WriteResponse(250, response);}void PSMTPServer::OnEHLO(const PCaselessString & remoteHost){  extendedHello = TRUE;  ServerReset();  PCaselessString peerHost;  PIPSocket * socket = GetSocket();  if (socket != NULL)    peerHost = socket->GetPeerHostName();  PString response = PIPSocket::GetHostName() & "Hello" & peerHost + ", ";  if (remoteHost == peerHost)    response += ", pleased to meet you.";  else if (remoteHost.IsEmpty())    response += "why do you wish to remain anonymous?";  else    response += "why do you wish to call yourself \"" + remoteHost + "\"?";  response += "\nHELP\nVERB\nONEX\nMULT\nEXPN\nTICK\n8BITMIME\n";  WriteResponse(250, response);}void PSMTPServer::OnQUIT(){  WriteResponse(221, PIPSocket::GetHostName() + " closing connection, goodbye.");  Close();}void PSMTPServer::OnHELP(){  WriteResponse(214, "No help here.");}void PSMTPServer::OnNOOP(){  WriteResponse(250, "Ok");}void PSMTPServer::OnTURN(){  WriteResponse(502, "I don't do that yet. Sorry.");}void PSMTPServer::OnRSET(){  ServerReset();  WriteResponse(250, "Reset state.");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -