📄 inetmail.cxx
字号:
/* * inetmail.cxx * * Internet Mail classes. * * Portable Windows Library * * Copyright (c) 1993-1998 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. * * Portions are Copyright (C) 1993 Free Software Foundation, Inc. * All Rights Reserved. * * Contributor(s): ______________________________________. * * $Log: inetmail.cxx,v $ * 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>static 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"};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 (IsOpen() && haveHello) { SetReadTimeout(60000); ok = ExecuteCommand(QUIT, "") == '2'; } return PInternetProtocol::Close() && ok;}BOOL 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) == '2') haveHello = extendedHello = TRUE; } if (!haveHello) { extendedHello = FALSE; if (eightBitMIME) return FALSE; if (ExecuteCommand(HELO, localHost) != '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 + '>') != '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] + '>') != '2') return FALSE; } if (ExecuteCommand(DATA, PString()) != '3') return FALSE; stuffingState = StuffIdle; return TRUE;}BOOL PSMTPClient::EndMessage(){ flush(); stuffingState = DontStuff; 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.");}void PSMTPServer::OnVRFY(const PCaselessString & name){ PString expandedName; switch (LookUpName(name, expandedName)) { case AmbiguousUser : WriteResponse(553, "User \"" + name + "\" ambiguous."); break; case ValidUser : WriteResponse(250, expandedName); break; case UnknownUser : WriteResponse(550, "Name \"" + name + "\" does not match anything."); break; default : WriteResponse(550, "Error verifying user \"" + name + "\"."); }}void PSMTPServer::OnEXPN(const PCaselessString &){ WriteResponse(502, "I don't do that. Sorry.");}static PINDEX ParseMailPath(const PCaselessString & args, const PCaselessString & subCmd, PString & name, PString & domain, PString & forwardList){ PINDEX colon = args.Find(':'); if (colon == P_MAX_INDEX) return 0; PCaselessString word = args.Left(colon).Trim(); if (subCmd != word) return 0; PINDEX leftAngle = args.Find('<', colon); if (leftAngle == P_MAX_INDEX) return 0; PINDEX finishQuote; PINDEX startQuote = args.Find('"', leftAngle); if (startQuote == P_MAX_INDEX) { colon = args.Find(':', leftAngle); if (colon == P_MAX_INDEX) colon = leftAngle; finishQuote = startQuote = colon+1; } else { finishQuote = args.Find('"', startQuote+1); if (finishQuote == P_MAX_INDEX) finishQuote = startQuote; colon = args.Find(':', leftAngle); if (colon > startQuote) colon = leftAngle; } PINDEX rightAngle = args.Find('>', finishQuote); if (rightAngle == P_MAX_INDEX) return 0; PINDEX at = args.Find('@', finishQuote); if (at > rightAngle) at = rightAngle; if (startQuote == finishQuote) finishQuote = at; name = args(startQuote, finishQuote-1); domain = args(at+1, rightAngle-1); forwardList = args(leftAngle+1, colon-1); return rightAngle+1;}void PSMTPServer::OnRCPT(const PCaselessString & recipient){ PCaselessString toName; PCaselessString toDomain; PCaselessString forwardList; if (ParseMailPath(recipient, "to", toName, toDomain, forwardList) == 0) WriteResponse(501, "Syntax error."); else { switch (ForwardDomain(toDomain, forwardList)) { case CannotForward : WriteResponse(550, "Cannot do forwarding."); break; case WillForward : if (!forwardList) forwardList += ":"; forwardList += toName; if (!toDomain) forwardList += "@" + toDomain; toNames.AppendString(toName); toDomains.AppendString(forwardList); break; case LocalDomain : { PString expandedName; switch (LookUpName(toName, expandedName)) { case ValidUser : WriteResponse(250, "Recipient " + toName + " Ok"); toNames.AppendString(toName); toDomains.AppendString(""); break; case AmbiguousUser : WriteResponse(553, "User ambiguous."); break; case UnknownUser : WriteResponse(550, "User unknown."); break; default : WriteResponse(550, "Error verifying user."); } } } }}void PSMTPServer::OnMAIL(const PCaselessString & sender){ sendCommand = WasMAIL; OnSendMail(sender);}void PSMTPServer::OnSEND(const PCaselessString & sender){ sendCommand = WasSEND; OnSendMail(sender);}void PSMTPServer::OnSAML(const PCaselessString & sender){ sendCommand = WasSAML; OnSendMail(sender);}void PSMTPServer::OnSOML(const PCaselessString & sender){ sendCommand = WasSOML; OnSendMail(sender);}void PSMTPServer::OnSendMail(const PCaselessString & sender){ if (!fromAddress) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -