提交 13424f74bf48b98e5caf83e62fcd079b84f8abcc

作者 LJH 李佳桓
1 个父辈 08cbfb79

add

正在显示 1 个修改的文件 包含 519 行增加0 行删除
  1 +/*
  2 + * Copyright 2009 Stephen Liu
  3 + * For license terms, see the file COPYING along with this library.
  4 + */
  5 +
  6 +#include <string.h>
  7 +#include <stdio.h>
  8 +#include <ctype.h>
  9 +
  10 +#include "spsmtp.hpp"
  11 +
  12 +#include "spbuffer.hpp"
  13 +#include "sphandler.hpp"
  14 +#include "sprequest.hpp"
  15 +#include "spresponse.hpp"
  16 +#include "spmsgdecoder.hpp"
  17 +#include "sputils.hpp"
  18 +
  19 +SP_SmtpHandler :: ~SP_SmtpHandler()
  20 +{
  21 +}
  22 +
  23 +void SP_SmtpHandler :: error()
  24 +{
  25 +}
  26 +
  27 +void SP_SmtpHandler :: timeout()
  28 +{
  29 +}
  30 +
  31 +int SP_SmtpHandler :: welcome( const char * clientIP, const char * serverIP, SP_Buffer * reply )
  32 +{
  33 + reply->append( "220 SMTP service ready\n" );
  34 +
  35 + return eAccept;
  36 +}
  37 +
  38 +int SP_SmtpHandler :: help( const char * args, SP_Buffer * reply )
  39 +{
  40 + reply->append( "250 HELP HELO EHLO MAIL RCPT DATA NOOP RSET QUIT\r\n" );
  41 +
  42 + return eAccept;
  43 +}
  44 +
  45 +int SP_SmtpHandler :: helo( const char * args, SP_Buffer * reply )
  46 +{
  47 + reply->append( "250 OK\n" );
  48 +
  49 + return eAccept;
  50 +}
  51 +
  52 +int SP_SmtpHandler :: ehlo( const char * args, SP_Buffer * reply )
  53 +{
  54 + reply->append( "250-OK\n" );
  55 + reply->append( "250-AUTH=LOGIN\n" );
  56 + reply->append( "250 HELP\n" );
  57 +
  58 + return eAccept;
  59 +}
  60 +
  61 +int SP_SmtpHandler :: auth( const char * user, const char * pass, SP_Buffer * reply )
  62 +{
  63 + reply->append( "535 Authenticate failed\n" );
  64 +
  65 + return eReject;
  66 +}
  67 +
  68 +int SP_SmtpHandler :: noop( const char * args, SP_Buffer * reply )
  69 +{
  70 + reply->append( "250 OK\n" );
  71 +
  72 + return eAccept;
  73 +}
  74 +
  75 +//---------------------------------------------------------
  76 +
  77 +SP_SmtpHandlerList :: SP_SmtpHandlerList()
  78 +{
  79 + mList = new SP_ArrayList();
  80 +}
  81 +
  82 +SP_SmtpHandlerList :: ~SP_SmtpHandlerList()
  83 +{
  84 + for( int i = 0; i < mList->getCount(); i++ ) {
  85 + delete (SP_SmtpHandler*)mList->getItem(i);
  86 + }
  87 +
  88 + delete mList, mList = NULL;
  89 +}
  90 +
  91 +int SP_SmtpHandlerList :: getCount()
  92 +{
  93 + return mList->getCount();
  94 +}
  95 +
  96 +void SP_SmtpHandlerList :: append( SP_SmtpHandler * handler )
  97 +{
  98 + mList->append( handler );
  99 +}
  100 +
  101 +SP_SmtpHandler * SP_SmtpHandlerList :: getItem( int index )
  102 +{
  103 + return (SP_SmtpHandler*)mList->getItem( index );
  104 +}
  105 +
  106 +//---------------------------------------------------------
  107 +
  108 +SP_SmtpHandlerFactory :: ~SP_SmtpHandlerFactory()
  109 +{
  110 +}
  111 +
  112 +//---------------------------------------------------------
  113 +
  114 +class SP_SmtpSession {
  115 +public:
  116 + SP_SmtpSession( SP_SmtpHandlerFactory * handlerFactory );
  117 + ~SP_SmtpSession();
  118 +
  119 + enum { eStepOther = 0, eStepUser = 1, eStepPass = 2 };
  120 + void setAuthStep( int step );
  121 + int getAuthStep();
  122 +
  123 + void setUser( const char * user );
  124 + const char * getUser();
  125 +
  126 + void setPass( const char * pass );
  127 + const char * getPass();
  128 +
  129 + void setSeenAuth( int seenAuth );
  130 + int getSeenAuth();
  131 +
  132 + void setSeenHelo( int seenHelo );
  133 + int getSeenHelo();
  134 +
  135 + void setSeenSender( int seenSender );
  136 + int getSeenSender();
  137 +
  138 + void addRcpt();
  139 + int getRcptCount();
  140 +
  141 + void setDataMode( int mode );
  142 + int getDataMode();
  143 +
  144 + int getSeenData();
  145 +
  146 + void reset();
  147 +
  148 + SP_SmtpHandler * getHandler();
  149 +
  150 +private:
  151 + int mAuthStep;
  152 + int mSeenAuth;
  153 +
  154 + char mUser[ 128 ], mPass[ 128 ];
  155 +
  156 + int mSeenHelo;
  157 + int mSeenSender;
  158 + int mRcptCount;
  159 + int mSeenData;
  160 +
  161 + int mDataMode;
  162 +
  163 + SP_SmtpHandler * mHandler;
  164 +
  165 + SP_SmtpHandlerFactory * mHandlerFactory;
  166 +};
  167 +
  168 +SP_SmtpSession :: SP_SmtpSession( SP_SmtpHandlerFactory * handlerFactory )
  169 +{
  170 + mHandler = NULL;
  171 + mHandlerFactory = handlerFactory;
  172 +
  173 + mSeenHelo = 0;
  174 + mSeenAuth = 0;
  175 + mAuthStep = eStepOther;
  176 +
  177 + memset( mUser, 0, sizeof( mUser ) );
  178 + memset( mPass, 0, sizeof( mPass ) );
  179 +
  180 + reset();
  181 +}
  182 +
  183 +SP_SmtpSession :: ~SP_SmtpSession()
  184 +{
  185 + if( NULL != mHandler ) delete mHandler;
  186 +}
  187 +
  188 +void SP_SmtpSession :: reset()
  189 +{
  190 + mSeenSender = 0;
  191 + mRcptCount = 0;
  192 + mSeenData = 0;
  193 +
  194 + mDataMode = 0;
  195 +}
  196 +
  197 +void SP_SmtpSession :: setAuthStep( int step )
  198 +{
  199 + mAuthStep = step;
  200 +}
  201 +
  202 +int SP_SmtpSession :: getAuthStep()
  203 +{
  204 + return mAuthStep;
  205 +}
  206 +
  207 +void SP_SmtpSession :: setUser( const char * user )
  208 +{
  209 + sp_strlcpy( mUser, user, sizeof( mUser ) );
  210 +}
  211 +
  212 +const char * SP_SmtpSession :: getUser()
  213 +{
  214 + return mUser;
  215 +}
  216 +
  217 +void SP_SmtpSession :: setPass( const char * pass )
  218 +{
  219 + sp_strlcpy( mPass, pass, sizeof( mPass ) );
  220 +}
  221 +
  222 +const char * SP_SmtpSession :: getPass()
  223 +{
  224 + return mPass;
  225 +}
  226 +
  227 +void SP_SmtpSession :: setSeenAuth( int seenAuth )
  228 +{
  229 + mSeenAuth = seenAuth;
  230 +}
  231 +
  232 +int SP_SmtpSession :: getSeenAuth()
  233 +{
  234 + return mSeenAuth;
  235 +}
  236 +
  237 +void SP_SmtpSession :: setSeenHelo( int seenHelo )
  238 +{
  239 + mSeenHelo = seenHelo;
  240 +}
  241 +
  242 +int SP_SmtpSession :: getSeenHelo()
  243 +{
  244 + return mSeenHelo;
  245 +}
  246 +
  247 +void SP_SmtpSession :: setSeenSender( int seenSender )
  248 +{
  249 + mSeenSender = seenSender;
  250 +}
  251 +
  252 +int SP_SmtpSession :: getSeenSender()
  253 +{
  254 + return mSeenSender;
  255 +}
  256 +
  257 +void SP_SmtpSession :: addRcpt()
  258 +{
  259 + mRcptCount++;
  260 +}
  261 +
  262 +int SP_SmtpSession :: getRcptCount()
  263 +{
  264 + return mRcptCount;
  265 +}
  266 +
  267 +void SP_SmtpSession :: setDataMode( int mode )
  268 +{
  269 + mDataMode = mode;
  270 +
  271 + if( 1 == mode ) mSeenData = 1;
  272 +}
  273 +
  274 +int SP_SmtpSession :: getDataMode()
  275 +{
  276 + return mDataMode;
  277 +}
  278 +
  279 +int SP_SmtpSession :: getSeenData()
  280 +{
  281 + return mSeenData;
  282 +}
  283 +
  284 +SP_SmtpHandler * SP_SmtpSession :: getHandler()
  285 +{
  286 + if( NULL == mHandler ) mHandler = mHandlerFactory->create();
  287 +
  288 + return mHandler;
  289 +}
  290 +
  291 +//---------------------------------------------------------
  292 +
  293 +class SP_SmtpHandlerAdapter : public SP_Handler {
  294 +public:
  295 + SP_SmtpHandlerAdapter( SP_SmtpHandlerFactory * handlerFactory );
  296 +
  297 + virtual ~SP_SmtpHandlerAdapter();
  298 +
  299 + // return -1 : terminate session, 0 : continue
  300 + virtual int start( SP_Request * request, SP_Response * response );
  301 +
  302 + // return -1 : terminate session, 0 : continue
  303 + virtual int handle( SP_Request * request, SP_Response * response );
  304 +
  305 + virtual void error( SP_Response * response );
  306 +
  307 + virtual void timeout( SP_Response * response );
  308 +
  309 + virtual void close();
  310 +
  311 +private:
  312 + SP_SmtpSession * mSession;
  313 +};
  314 +
  315 +SP_SmtpHandlerAdapter :: SP_SmtpHandlerAdapter( SP_SmtpHandlerFactory * handlerFactory )
  316 +{
  317 + mSession = new SP_SmtpSession( handlerFactory );
  318 +}
  319 +
  320 +SP_SmtpHandlerAdapter :: ~SP_SmtpHandlerAdapter()
  321 +{
  322 + delete mSession;
  323 +}
  324 +
  325 +int SP_SmtpHandlerAdapter :: start( SP_Request * request, SP_Response * response )
  326 +{
  327 + SP_Buffer * reply = response->getReply()->getMsg();
  328 +
  329 + int ret = mSession->getHandler()->welcome( request->getClientIP(),
  330 + request->getServerIP(), reply );
  331 +
  332 + if( NULL == reply->find( "\n", 1 ) ) reply->append( "\n" );
  333 +
  334 + request->setMsgDecoder( new SP_LineMsgDecoder() );
  335 +
  336 + return ret;
  337 +}
  338 +
  339 +int SP_SmtpHandlerAdapter :: handle( SP_Request * request, SP_Response * response )
  340 +{
  341 + int ret = SP_SmtpHandler::eAccept;
  342 +
  343 + SP_Buffer * reply = response->getReply()->getMsg();
  344 +
  345 + if( mSession->getDataMode() ) {
  346 + SP_DotTermChunkMsgDecoder * decoder = (SP_DotTermChunkMsgDecoder*)request->getMsgDecoder();
  347 +
  348 + char * data = (char*)decoder->getMsg();
  349 + ret = mSession->getHandler()->data( data, reply );
  350 + free( data );
  351 +
  352 + mSession->setDataMode( 0 );
  353 + request->setMsgDecoder( new SP_LineMsgDecoder() );
  354 +
  355 + } else if( SP_SmtpSession::eStepUser == mSession->getAuthStep() ) {
  356 + const char * line = ((SP_LineMsgDecoder*)(request->getMsgDecoder()))->getMsg();
  357 + mSession->setUser( line );
  358 + mSession->setAuthStep( SP_SmtpSession::eStepPass );
  359 + reply->append( "334 UGFzc3dvcmQ6\r\n" );
  360 +
  361 + } else if( SP_SmtpSession::eStepPass == mSession->getAuthStep() ) {
  362 + const char * line = ((SP_LineMsgDecoder*)(request->getMsgDecoder()))->getMsg();
  363 + mSession->setPass( line );
  364 + mSession->setAuthStep( SP_SmtpSession::eStepOther );
  365 + ret = mSession->getHandler()->auth( mSession->getUser(), mSession->getPass(), reply );
  366 + if( SP_SmtpHandler::eAccept == ret ) mSession->setSeenAuth( 1 );
  367 +
  368 + } else {
  369 + const char * line = ((SP_LineMsgDecoder*)(request->getMsgDecoder()))->getMsg();
  370 +
  371 + char cmd[ 128 ] = { 0 };
  372 + const char * args = NULL;
  373 +
  374 + sp_strtok( line, 0, cmd, sizeof( cmd ), ' ', &args );
  375 +
  376 + if( 0 == strcasecmp( cmd, "EHLO" ) ) {
  377 + if( NULL != args ) {
  378 + if( 0 == mSession->getSeenHelo() ) {
  379 + ret = mSession->getHandler()->ehlo( args, reply );
  380 + if( SP_SmtpHandler::eAccept == ret ) mSession->setSeenHelo( 1 );
  381 + } else {
  382 + reply->append( "503 Duplicate EHLO\r\n" );
  383 + }
  384 + } else {
  385 + reply->append( "501 Syntax: EHLO <hostname>\r\n" );
  386 + }
  387 +
  388 + } else if( 0 == strcasecmp( cmd, "AUTH" ) ) {
  389 + if( 0 == mSession->getSeenHelo() ) {
  390 + reply->append( "503 Error: send EHLO first\r\n" );
  391 + } else if( mSession->getSeenAuth() ) {
  392 + reply->append( "503 Duplicate AUTH\r\n" );
  393 + } else {
  394 + if( NULL != args ) {
  395 + if( 0 == strcasecmp( args, "LOGIN" ) ) {
  396 + reply->append( "334 VXNlcm5hbWU6\r\n" );
  397 + mSession->setAuthStep( SP_SmtpSession::eStepUser );
  398 + } else {
  399 + reply->append( "504 Unrecognized authentication type.\r\n" );
  400 + }
  401 + } else {
  402 + reply->append( "501 Syntax: AUTH LOGIN\r\n" );
  403 + }
  404 + }
  405 +
  406 + } else if( 0 == strcasecmp( cmd, "HELO" ) ) {
  407 + if( NULL != args ) {
  408 + if( 0 == mSession->getSeenHelo() ) {
  409 + ret = mSession->getHandler()->helo( args, reply );
  410 + if( SP_SmtpHandler::eAccept == ret ) mSession->setSeenHelo( 1 );
  411 + } else {
  412 + reply->append( "503 Duplicate HELO\r\n" );
  413 + }
  414 + } else {
  415 + reply->append( "501 Syntax: HELO <hostname>\r\n" );
  416 + }
  417 +
  418 + } else if( 0 == strcasecmp( cmd, "MAIL" ) ) {
  419 + if( 0 == mSession->getSeenHelo() ) {
  420 + reply->append( "503 Error: send HELO first\r\n" );
  421 + } else if( mSession->getSeenSender() ) {
  422 + reply->append( "503 Sender already specified.\r\n" );
  423 + } else {
  424 + if( NULL != args ) {
  425 + if( 0 == strncasecmp( args, "FROM:", 5 ) ) args += 5;
  426 + for( ; isspace( *args ); ) args++;
  427 + ret = mSession->getHandler()->from( args, reply );
  428 + if( SP_SmtpHandler::eAccept == ret ) mSession->setSeenSender( 1 );
  429 + } else {
  430 + reply->append( "501 Syntax: MAIL FROM:<address>\r\n" );
  431 + }
  432 + }
  433 +
  434 + } else if( 0 == strcasecmp( cmd, "RCPT" ) ) {
  435 + if( 0 == mSession->getSeenHelo() ) {
  436 + reply->append( "503 Error: send HELO first\r\n" );
  437 + } else if( 0 == mSession->getSeenSender() ) {
  438 + reply->append( "503 Error: need MAIL command\r\n" );
  439 + } else if( mSession->getSeenData() ) {
  440 + reply->append( "503 Bad sequence of commands\r\n" );
  441 + } else {
  442 + if( NULL != args ) {
  443 + if( 0 == strncasecmp( args, "TO:", 3 ) ) args += 3;
  444 + for( ; isspace( *args ); ) args++;
  445 + ret = mSession->getHandler()->rcpt( args, reply );
  446 + if( SP_SmtpHandler::eAccept == ret ) mSession->addRcpt();
  447 + } else {
  448 + reply->append( "501 Syntax: RCPT TO:<address>\r\n" );
  449 + }
  450 + }
  451 +
  452 + } else if( 0 == strcasecmp( cmd, "DATA" ) ) {
  453 + if( 0 == mSession->getSeenHelo() ) {
  454 + reply->append( "503 Error: send HELO first\r\n" );
  455 + } else if( 0 == mSession->getSeenSender() ) {
  456 + reply->append( "503 Error: need MAIL command\r\n" );
  457 + } else if( mSession->getRcptCount() <= 0 ) {
  458 + reply->append( "503 Error: need RCPT command\r\n" );
  459 + } else {
  460 + request->setMsgDecoder( new SP_DotTermChunkMsgDecoder() );
  461 + reply->append( "354 Start mail input; end with <CRLF>.<CRLF>\r\n" );
  462 + mSession->setDataMode( 1 );
  463 + }
  464 +
  465 + } else if( 0 == strcasecmp( cmd, "RSET" ) ) {
  466 + ret = mSession->getHandler()->rset( reply );
  467 + mSession->reset();
  468 +
  469 + } else if( 0 == strcasecmp( cmd, "NOOP" ) ) {
  470 + ret = mSession->getHandler()->noop( args, reply );
  471 +
  472 + } else if( 0 == strcasecmp( cmd, "HELP" ) ) {
  473 + ret = mSession->getHandler()->help( args, reply );
  474 +
  475 + } else if( 0 == strcasecmp( cmd, "QUIT" ) ) {
  476 + reply->append( "221 Closing connection. Good bye.\r\n" );
  477 + ret = SP_SmtpHandler::eClose;
  478 +
  479 + } else {
  480 + reply->printf( "500 Syntax error, command unrecognized <%s>.\r\n", cmd );
  481 + }
  482 + }
  483 +
  484 + if( NULL == reply->find( "\n", 1 ) ) reply->append( "\n" );
  485 +
  486 + return SP_SmtpHandler::eClose == ret ? -1 : 0;
  487 +}
  488 +
  489 +void SP_SmtpHandlerAdapter :: error( SP_Response * response )
  490 +{
  491 + mSession->getHandler()->error();
  492 +}
  493 +
  494 +void SP_SmtpHandlerAdapter :: timeout( SP_Response * response )
  495 +{
  496 + mSession->getHandler()->timeout();
  497 +}
  498 +
  499 +void SP_SmtpHandlerAdapter :: close()
  500 +{
  501 +}
  502 +
  503 +//---------------------------------------------------------
  504 +
  505 +SP_SmtpHandlerAdapterFactory :: SP_SmtpHandlerAdapterFactory( SP_SmtpHandlerFactory * factory )
  506 +{
  507 + mFactory = factory;
  508 +}
  509 +
  510 +SP_SmtpHandlerAdapterFactory :: ~SP_SmtpHandlerAdapterFactory()
  511 +{
  512 + delete mFactory;
  513 +}
  514 +
  515 +SP_Handler * SP_SmtpHandlerAdapterFactory :: create() const
  516 +{
  517 + return new SP_SmtpHandlerAdapter( mFactory );
  518 +}
  519 +
... ...
注册登录 后发表评论