www.pudn.com > SMTP-C.rar > smtp.c
/* * The contents of this file are subject to the Netscape 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/NPL/. * * 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 the Netscape Messaging Access SDK Version 3.5 code, * released on or about June 15, 1998. * * The Initial Developer of the Original Code is Netscape Communications * Corporation. Portions created by Netscape are Copyright (C) 1998 Netscape * Communications Corporation. All Rights Reserved. * * Contributor(s): ______________________________________. */ /* * Copyright (c) 1997 and 1998 Netscape Communications Corporation * (http://home.netscape.com/misc/trademarks.html) */ /* * smtp.c * @author derekt@netscape.com * @version 1.0 */ #include "nsmail.h" #include "smtp.h" #include "smtppriv.h" #include "nsio.h" #include#include #include int smtp_initialize( smtpClient_t ** out_ppSMTP, smtpSink_t * in_pSMTPSink ) { smtpClient_i_t * l_pSMTP; /* Parameter validation. */ if ( out_ppSMTP == NULL || (*out_ppSMTP) != NULL || in_pSMTPSink == NULL ) { return NSMAIL_ERR_INVALIDPARAM; } /* Create the client. */ l_pSMTP = (smtpClient_i_t*)malloc( sizeof(smtpClient_i_t) ); if ( l_pSMTP == NULL ) { return NSMAIL_ERR_OUTOFMEMORY; } /* Set the data members of the smtpClient_t structure. */ l_pSMTP->timeout = -1; l_pSMTP->chunkSize = 1024; l_pSMTP->smtpSink = in_pSMTPSink; l_pSMTP->mustProcess = FALSE; l_pSMTP->pipelining = FALSE; l_pSMTP->lastSentChar = '\n'; l_pSMTP->pCommandList = NULL; l_pSMTP->fDATASent = FALSE; memset(&(l_pSMTP->io), 0, sizeof( IO_t ) ); l_pSMTP->messageData = (char*)malloc( l_pSMTP->chunkSize * sizeof(char) ); if ( l_pSMTP->messageData == NULL ) { return NSMAIL_ERR_OUTOFMEMORY; } *out_ppSMTP = l_pSMTP; /* Initialize the IO structure. */ return IO_initialize( (&l_pSMTP->io), MAX_BUFFER_LENGTH, l_pSMTP->chunkSize ); } void smtp_free( smtpClient_t ** in_ppSMTP ) { if ( in_ppSMTP == NULL || *in_ppSMTP == NULL ) { return; } /* Free the members of the IO structure. */ IO_free( &((*in_ppSMTP)->io) ); /* Remove all the elements from the linked list. */ RemoveAllElements( &((*in_ppSMTP)->pCommandList) ); if ( (*in_ppSMTP)->messageData != NULL ) { free( (*in_ppSMTP)->messageData ); } /* Free the client. */ free( (*in_ppSMTP) ); *in_ppSMTP = NULL; } int smtp_bdat( smtpClient_t * in_pSMTP, const char * in_data, unsigned int in_length, boolean in_fLast ) { int l_nReturnCode; /* Check for errors. */ if ( in_pSMTP == NULL || in_data == NULL ) { return NSMAIL_ERR_INVALIDPARAM; } if ( in_pSMTP->mustProcess ) { return NSMAIL_ERR_MUSTPROCESSRESPONSES; } if ( in_pSMTP->fDATASent ) { return NSMAIL_ERR_SENDDATA; } l_nReturnCode = IO_write( &(in_pSMTP->io), bdat, strlen(bdat) ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } /* Send the command. */ sprintf( in_pSMTP->commandBuffer, "%d", in_length ); if ( in_fLast ) { l_nReturnCode = IO_write(&(in_pSMTP->io), bdatLast, strlen(bdatLast)); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } } l_nReturnCode = IO_write(&(in_pSMTP->io), eoline, strlen(eoline)); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } l_nReturnCode = IO_write( &(in_pSMTP->io), in_data, in_length ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } /* Store the command type on the pending response list. */ l_nReturnCode = AddElement( &(in_pSMTP->pCommandList), (void*)&SMTPResponse_BDAT ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } if ( in_pSMTP->pipelining == FALSE ) { in_pSMTP->mustProcess = TRUE; } return NSMAIL_OK; } int smtp_connect( smtpClient_t * in_pSMTP, const char * in_server, unsigned short in_port ) { int l_nReturnCode; /* Check for errors. */ if ( in_pSMTP == NULL || in_server == NULL ) { return NSMAIL_ERR_INVALIDPARAM; } if ( in_pSMTP->mustProcess ) { return NSMAIL_ERR_MUSTPROCESSRESPONSES; } /* Reset data members. */ in_pSMTP->pipelining = FALSE; in_pSMTP->lastSentChar = '\n'; RemoveAllElements( &(in_pSMTP->pCommandList) ); /* Connect to the server. */ if ( in_port == 0 ) { in_port = DEFAULT_SMTP_PORT; } l_nReturnCode = IO_connect( &(in_pSMTP->io), in_server, in_port ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } /* Store the command type on the pending response list. */ l_nReturnCode = AddElement( &(in_pSMTP->pCommandList), (void*)&SMTPResponse_CONN ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } in_pSMTP->mustProcess = TRUE; return NSMAIL_OK; } int smtp_data( smtpClient_t * in_pSMTP ) { int l_nReturnCode; /* Check for errors. */ if ( in_pSMTP == NULL ) { return NSMAIL_ERR_INVALIDPARAM; } if ( in_pSMTP->mustProcess ) { return NSMAIL_ERR_MUSTPROCESSRESPONSES; } if ( in_pSMTP->fDATASent ) { return NSMAIL_ERR_SENDDATA; } /* Send the command. */ l_nReturnCode = IO_send( &(in_pSMTP->io), data, FALSE ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } /* Store the command type on the pending response list. */ l_nReturnCode = AddElement( &(in_pSMTP->pCommandList), (void*)&SMTPResponse_DATA ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } in_pSMTP->mustProcess = TRUE; return NSMAIL_OK; } int smtp_disconnect( smtpClient_t * in_pSMTP ) { /* Disconnect from the server. */ return IO_disconnect( &(in_pSMTP->io) ); } int smtp_ehlo( smtpClient_t * in_pSMTP, const char * in_domain ) { int l_nReturnCode; /* Check for errors. */ if ( in_pSMTP == NULL || in_domain == NULL ) { return NSMAIL_ERR_INVALIDPARAM; } if ( in_pSMTP->mustProcess ) { return NSMAIL_ERR_MUSTPROCESSRESPONSES; } if ( in_pSMTP->fDATASent ) { return NSMAIL_ERR_SENDDATA; } /* Send the command. */ l_nReturnCode = IO_write( &(in_pSMTP->io), ehlo, strlen(ehlo) ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } l_nReturnCode = IO_send( &(in_pSMTP->io), in_domain, FALSE ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } /* Store the command type on the pending response list. */ l_nReturnCode = AddElement( &(in_pSMTP->pCommandList), (void*)&SMTPResponse_EHLO ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } in_pSMTP->mustProcess = TRUE; return NSMAIL_OK; } int smtp_expand( smtpClient_t * in_pSMTP, const char * in_mailingList ) { int l_nReturnCode; /* Check for errors. */ if ( in_pSMTP == NULL || in_mailingList == NULL ) { return NSMAIL_ERR_INVALIDPARAM; } if ( in_pSMTP->mustProcess ) { return NSMAIL_ERR_MUSTPROCESSRESPONSES; } if ( in_pSMTP->fDATASent ) { return NSMAIL_ERR_SENDDATA; } /* Send the command. */ l_nReturnCode = IO_write( &(in_pSMTP->io), expn, strlen(expn) ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } l_nReturnCode = IO_send( &(in_pSMTP->io), in_mailingList, FALSE ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } /* Store the command type on the pending response list. */ l_nReturnCode = AddElement( &(in_pSMTP->pCommandList), (void*)&SMTPResponse_EXPN ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } in_pSMTP->mustProcess = TRUE; return NSMAIL_OK; } int smtp_help( smtpClient_t * in_pSMTP, const char * in_helpTopic ) { int l_nReturnCode; /* Check for errors. */ if ( in_pSMTP == NULL ) { return NSMAIL_ERR_INVALIDPARAM; } if ( in_pSMTP->mustProcess ) { return NSMAIL_ERR_MUSTPROCESSRESPONSES; } if ( in_pSMTP->fDATASent ) { return NSMAIL_ERR_SENDDATA; } /* Send the command. */ l_nReturnCode = IO_write( &(in_pSMTP->io), help, strlen(help) ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } if ( in_helpTopic != NULL ) { l_nReturnCode = IO_send( &(in_pSMTP->io), in_helpTopic, FALSE ); } else { l_nReturnCode = IO_send( &(in_pSMTP->io), empty, FALSE ); } if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } /* Store the command type on the pending response list. */ l_nReturnCode = AddElement( &(in_pSMTP->pCommandList), (void*)&SMTPResponse_HELP ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } in_pSMTP->mustProcess = TRUE; return NSMAIL_OK; } int smtp_mailFrom( smtpClient_t * in_pSMTP, const char * in_reverseAddress, const char * in_esmtpParams ) { int l_nReturnCode; /* Check for errors. */ if ( in_pSMTP == NULL || in_reverseAddress == NULL ) { return NSMAIL_ERR_INVALIDPARAM; } if ( in_pSMTP->mustProcess ) { return NSMAIL_ERR_MUSTPROCESSRESPONSES; } if ( in_pSMTP->fDATASent ) { return NSMAIL_ERR_SENDDATA; } l_nReturnCode = IO_write( &(in_pSMTP->io), mailFrom, strlen(mailFrom) ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } l_nReturnCode = IO_write( &(in_pSMTP->io), in_reverseAddress, strlen(in_reverseAddress) ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } l_nReturnCode = IO_write( &(in_pSMTP->io), rBracket, strlen(rBracket) ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } if ( in_esmtpParams != NULL ) { l_nReturnCode = IO_write( &(in_pSMTP->io), in_esmtpParams, strlen(in_esmtpParams) ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } } l_nReturnCode = IO_send( &(in_pSMTP->io), empty, in_pSMTP->pipelining ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } /* Store the command type on the pending response list. */ l_nReturnCode = AddElement( &(in_pSMTP->pCommandList), (void*)&SMTPResponse_MAIL ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } if ( in_pSMTP->pipelining == FALSE ) { in_pSMTP->mustProcess = TRUE; } return NSMAIL_OK; } int smtp_noop( smtpClient_t * in_pSMTP ) { int l_nReturnCode; /* Check for errors. */ if ( in_pSMTP == NULL ) { return NSMAIL_ERR_INVALIDPARAM; } if ( in_pSMTP->mustProcess ) { return NSMAIL_ERR_MUSTPROCESSRESPONSES; } if ( in_pSMTP->fDATASent ) { return NSMAIL_ERR_SENDDATA; } l_nReturnCode = IO_send( &(in_pSMTP->io), noop, FALSE ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } /* Store the command type on the pending response list. */ l_nReturnCode = AddElement( &(in_pSMTP->pCommandList), (void*)&SMTPResponse_NOOP ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } in_pSMTP->mustProcess = TRUE; return NSMAIL_OK; } int smtp_quit( smtpClient_t * in_pSMTP ) { int l_nReturnCode; /* Check for errors. */ if ( in_pSMTP == NULL ) { return NSMAIL_ERR_INVALIDPARAM; } if ( in_pSMTP->mustProcess ) { return NSMAIL_ERR_MUSTPROCESSRESPONSES; } if ( in_pSMTP->fDATASent ) { return NSMAIL_ERR_SENDDATA; } l_nReturnCode = IO_send( &(in_pSMTP->io), quit, FALSE ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } /* Store the command type on the pending response list. */ l_nReturnCode = AddElement( &(in_pSMTP->pCommandList), (void*)&SMTPResponse_QUIT ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } in_pSMTP->mustProcess = TRUE; return NSMAIL_OK; } int smtp_rcptTo( smtpClient_t * in_pSMTP, const char * in_forwardAddress, const char * in_esmtpParams ) { int l_nReturnCode; /* Check for errors. */ if ( in_pSMTP == NULL || in_forwardAddress == NULL ) { return NSMAIL_ERR_INVALIDPARAM; } if ( in_pSMTP->mustProcess ) { return NSMAIL_ERR_MUSTPROCESSRESPONSES; } if ( in_pSMTP->fDATASent ) { return NSMAIL_ERR_SENDDATA; } l_nReturnCode = IO_write( &(in_pSMTP->io), rcptTo, strlen(rcptTo) ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } l_nReturnCode = IO_write( &(in_pSMTP->io), in_forwardAddress, strlen(in_forwardAddress) ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } l_nReturnCode = IO_write( &(in_pSMTP->io), rBracket, strlen(rBracket) ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } if ( in_esmtpParams != NULL ) { l_nReturnCode = IO_write( &(in_pSMTP->io), in_esmtpParams, strlen(in_esmtpParams) ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } } l_nReturnCode = IO_send( &(in_pSMTP->io), empty, in_pSMTP->pipelining ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } /* Store the command type on the pending response list. */ l_nReturnCode = AddElement( &(in_pSMTP->pCommandList), (void*)&SMTPResponse_RCPT ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } if ( in_pSMTP->pipelining == FALSE ) { in_pSMTP->mustProcess = TRUE; } return NSMAIL_OK; } int smtp_reset( smtpClient_t * in_pSMTP ) { int l_nReturnCode; /* Check for errors. */ if ( in_pSMTP == NULL ) { return NSMAIL_ERR_INVALIDPARAM; } if ( in_pSMTP->mustProcess ) { return NSMAIL_ERR_MUSTPROCESSRESPONSES; } if ( in_pSMTP->fDATASent ) { return NSMAIL_ERR_SENDDATA; } l_nReturnCode = IO_send( &(in_pSMTP->io), rset, in_pSMTP->pipelining ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } /* Store the command type on the pending response list. */ l_nReturnCode = AddElement( &(in_pSMTP->pCommandList), (void*)&SMTPResponse_RSET ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } return NSMAIL_OK; } int smtp_send( smtpClient_t * in_pSMTP, const char * in_data ) { unsigned int l_offset = 0; unsigned int l_byteCount; unsigned int count; int l_nReturnCode; /* Check for errors. */ if ( in_pSMTP == NULL || in_data == NULL ) { return NSMAIL_ERR_INVALIDPARAM; } if ( in_pSMTP->mustProcess ) { return NSMAIL_ERR_MUSTPROCESSRESPONSES; } if ( in_pSMTP->fDATASent == FALSE ) { return NSMAIL_ERR_SENDDATA; } l_byteCount = strlen(in_data); for( count = 0; count < l_byteCount; count++ ) { if ( (in_pSMTP->lastSentChar == '\n') && (in_data[count] == '.') ) { l_nReturnCode = IO_write( &(in_pSMTP->io), &(in_data[l_offset]), count-l_offset ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } l_nReturnCode = IO_writeByte( &(in_pSMTP->io), '.' ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } l_offset = count; } in_pSMTP->lastSentChar = in_data[count]; } if ( l_offset < l_byteCount ) { l_nReturnCode = IO_write( &(in_pSMTP->io), &(in_data[l_offset]), l_byteCount-l_offset ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } } l_nReturnCode = IO_send(&(in_pSMTP->io), eomessage, in_pSMTP->pipelining); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } in_pSMTP->lastSentChar = '\n'; /* Store the command type on the pending response list. */ l_nReturnCode = AddElement( &(in_pSMTP->pCommandList), (void*)&SMTPResponse_SEND ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } if ( in_pSMTP->pipelining == FALSE ) { in_pSMTP->mustProcess = TRUE; } in_pSMTP->fDATASent = FALSE; return NSMAIL_OK; } int smtp_sendStream( smtpClient_t * in_pSMTP, nsmail_inputstream_t * in_inputStream ) { unsigned int l_offset; int l_nReturnCode; unsigned int count; unsigned int l_byteCount; /* Check for errors. */ if ( in_pSMTP == NULL || in_inputStream == NULL ) { return NSMAIL_ERR_INVALIDPARAM; } if ( in_pSMTP->mustProcess ) { return NSMAIL_ERR_MUSTPROCESSRESPONSES; } if ( in_pSMTP->fDATASent == FALSE ) { return NSMAIL_ERR_SENDDATA; } while ( (l_byteCount = in_inputStream->read( in_inputStream->rock, in_pSMTP->messageData, in_pSMTP->chunkSize ) ) != -1 ) { l_offset = 0; for( count = 0; count < l_byteCount; count++ ) { if ( (in_pSMTP->lastSentChar == '\n') && (in_pSMTP->messageData[count] == '.') ) { l_nReturnCode = IO_write( &(in_pSMTP->io), &(in_pSMTP->messageData[l_offset]), count-l_offset ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } l_nReturnCode = IO_writeByte( &(in_pSMTP->io), '.' ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } l_offset = count; } in_pSMTP->lastSentChar = in_pSMTP->messageData[count]; } if ( l_offset < l_byteCount ) { l_nReturnCode = IO_write( &(in_pSMTP->io), &(in_pSMTP->messageData[l_offset]), l_byteCount-l_offset ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } } } l_nReturnCode = IO_send(&(in_pSMTP->io), eomessage, in_pSMTP->pipelining); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } in_pSMTP->lastSentChar = '\n'; /* Store the command type on the pending response list. */ l_nReturnCode = AddElement( &(in_pSMTP->pCommandList), (void*)&SMTPResponse_SEND ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } if ( in_pSMTP->pipelining == FALSE ) { in_pSMTP->mustProcess = TRUE; } in_pSMTP->fDATASent = FALSE; return NSMAIL_OK; } int smtp_sendCommand( smtpClient_t * in_pSMTP, const char * in_command ) { int l_nReturnCode; /* Check for errors. */ if ( in_pSMTP == NULL || in_command == NULL ) { return NSMAIL_ERR_INVALIDPARAM; } if ( in_pSMTP->mustProcess ) { return NSMAIL_ERR_MUSTPROCESSRESPONSES; } if ( in_pSMTP->fDATASent ) { return NSMAIL_ERR_SENDDATA; } l_nReturnCode = IO_send( &(in_pSMTP->io), in_command, FALSE ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } /* Store the command type on the pending response list. */ l_nReturnCode = AddElement( &(in_pSMTP->pCommandList), (void*)&SMTPResponse_SENDCOMMAND ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } in_pSMTP->mustProcess = TRUE; return NSMAIL_OK; } int smtp_verify( smtpClient_t * in_pSMTP, const char * in_user ) { int l_nReturnCode; /* Check for errors. */ if ( in_pSMTP == NULL || in_user == NULL ) { return NSMAIL_ERR_INVALIDPARAM; } if ( in_pSMTP->mustProcess ) { return NSMAIL_ERR_MUSTPROCESSRESPONSES; } if ( in_pSMTP->fDATASent ) { return NSMAIL_ERR_SENDDATA; } l_nReturnCode = IO_write( &(in_pSMTP->io), vrfy, strlen(vrfy) ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } l_nReturnCode = IO_send( &(in_pSMTP->io), in_user, FALSE ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } /* Store the command type on the pending response list. */ l_nReturnCode = AddElement( &(in_pSMTP->pCommandList), (void*)&SMTPResponse_VRFY ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } in_pSMTP->mustProcess = TRUE; return NSMAIL_OK; } int smtp_processResponses( smtpClient_t * in_pSMTP ) { smtp_ResponseType_t * l_pCurrentResponse; LinkedList_t * l_pCurrentLink; int l_nReturnCode; /* Check for errors. */ if ( in_pSMTP == NULL ) { return NSMAIL_ERR_INVALIDPARAM; } /* Make sure that all buffered commands are sent. */ l_nReturnCode = IO_flush( &(in_pSMTP->io) ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } /* Continue to process responses while the list is not empty. */ /* or a timeout occurs. */ while ( in_pSMTP->pCommandList != NULL ) { l_pCurrentResponse = (smtp_ResponseType_t *)in_pSMTP->pCommandList->pData; switch ( *l_pCurrentResponse ) { case BDAT: l_nReturnCode = parseSingleLine( in_pSMTP, in_pSMTP->smtpSink->bdat ); break; case CONN: l_nReturnCode = parseSingleLine( in_pSMTP, in_pSMTP->smtpSink->connect ); if ( l_nReturnCode != NSMAIL_OK ) { IO_disconnect( &(in_pSMTP->io) ); } break; case DATA: l_nReturnCode = parseData( in_pSMTP ); break; case EHLO: l_nReturnCode = parseEhlo( in_pSMTP ); break; case EXPN: l_nReturnCode = parseMultiLine( in_pSMTP, in_pSMTP->smtpSink->expand, in_pSMTP->smtpSink->expandComplete ); break; case HELP: l_nReturnCode = parseMultiLine( in_pSMTP, in_pSMTP->smtpSink->help, in_pSMTP->smtpSink->helpComplete ); break; case MAIL: l_nReturnCode = parseSingleLine( in_pSMTP, in_pSMTP->smtpSink->mailFrom ); break; case NOOP: l_nReturnCode = parseSingleLine( in_pSMTP, in_pSMTP->smtpSink->noop ); break; case QUIT: l_nReturnCode = parseSingleLine( in_pSMTP, in_pSMTP->smtpSink->quit ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } l_nReturnCode = IO_disconnect( &(in_pSMTP->io) ); break; case RCPT: l_nReturnCode = parseSingleLine( in_pSMTP, in_pSMTP->smtpSink->rcptTo ); break; case RSET: l_nReturnCode = parseSingleLine( in_pSMTP, in_pSMTP->smtpSink->reset ); break; case SEND: l_nReturnCode = parseSingleLine( in_pSMTP, in_pSMTP->smtpSink->send ); break; case SENDCOMMAND: l_nReturnCode = parseMultiLine( in_pSMTP, in_pSMTP->smtpSink->sendCommand, in_pSMTP->smtpSink->sendCommandComplete ); break; case VRFY: l_nReturnCode = parseSingleLine( in_pSMTP, in_pSMTP->smtpSink->verify ); break; default: l_nReturnCode = NSMAIL_ERR_UNEXPECTED; break; } /* An timeout or an error has occured. */ if ( l_nReturnCode != NSMAIL_OK ) { if ( l_nReturnCode != NSMAIL_ERR_TIMEOUT ) { in_pSMTP->mustProcess = FALSE; } return l_nReturnCode; } /* Move to the next element in the pending response list. */ l_pCurrentLink = in_pSMTP->pCommandList; in_pSMTP->pCommandList = in_pSMTP->pCommandList->next; /* Free the current link in the pending response list. */ free ( l_pCurrentLink ); } in_pSMTP->mustProcess = FALSE; return NSMAIL_OK; } int smtp_setChunkSize( smtpClient_t * in_pSMTP, int in_chunkSize ) { if ( in_pSMTP == NULL || in_chunkSize <= 0 ) { return NSMAIL_ERR_INVALIDPARAM; } free( in_pSMTP->messageData ); in_pSMTP->messageData = (char*)malloc( in_chunkSize * sizeof(char) ); if ( in_pSMTP->messageData == NULL ) { return NSMAIL_ERR_OUTOFMEMORY; } in_pSMTP->chunkSize = in_chunkSize; return NSMAIL_OK; } int smtp_setPipelining( smtpClient_t * in_pSMTP, boolean in_enablePipelining ) { if ( in_pSMTP->pipeliningSupported == FALSE && in_enablePipelining ) { return NSMAIL_ERR_INVALIDPARAM; } in_pSMTP->pipelining = in_enablePipelining; return NSMAIL_OK; } int smtp_setResponseSink( smtpClient_t * in_pSMTP, smtpSink_t * in_pSMTPSink ) { if ( in_pSMTP == NULL || in_pSMTPSink == NULL ) { return NSMAIL_ERR_INVALIDPARAM; } in_pSMTP->smtpSink = in_pSMTPSink; return NSMAIL_OK; } int smtp_setTimeout( smtpClient_t * in_pSMTP, double in_timeout ) { if ( in_pSMTP == NULL ) { return NSMAIL_ERR_INVALIDPARAM; } return IO_setTimeout( &(in_pSMTP->io), in_timeout ); } int smtp_set_option( smtpClient_t * in_pSMTP, int in_option, void * in_pOptionData ) { if ( in_pSMTP == NULL || in_pOptionData == NULL ) { return NSMAIL_ERR_INVALIDPARAM; } switch ( in_option ) { case NSMAIL_OPT_IO_FN_PTRS: IO_setFunctions( &(in_pSMTP->io), (nsmail_io_fns_t *)in_pOptionData ); return NSMAIL_OK; break; default: return NSMAIL_ERR_UNEXPECTED; break; } } int smtp_get_option( smtpClient_t * in_pSMTP, int in_option, void * in_pOptionData ) { if ( in_pSMTP == NULL ) { return NSMAIL_ERR_INVALIDPARAM; } switch ( in_option ) { case NSMAIL_OPT_IO_FN_PTRS: IO_getFunctions( &(in_pSMTP->io), (nsmail_io_fns_t *)in_pOptionData ); return NSMAIL_OK; break; default: return NSMAIL_ERR_UNEXPECTED; break; } } static int setStatusInfo( const char * in_responseLine, int * out_responseCode ) { if ( in_responseLine == NULL || out_responseCode == NULL ) { return NSMAIL_ERR_INVALIDPARAM; } if ( strlen(in_responseLine) < 4 ) { return NSMAIL_ERR_PARSE; } *out_responseCode = atoi( in_responseLine ); if ( *out_responseCode == 0 ) { return NSMAIL_ERR_PARSE; } return NSMAIL_OK; } static int parseSingleLine( smtpClient_t * in_pSMTP, sinkMethod_t in_callback ) { /* The 3-digit response code. */ int l_nResponseCode; /* Read the next line of data from the socket. */ int l_nReturnCode = IO_readLine( &(in_pSMTP->io), in_pSMTP->responseLine, 512 ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } /* Parse out the response code and the message. */ l_nReturnCode = setStatusInfo( in_pSMTP->responseLine, &l_nResponseCode ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } if ( l_nResponseCode >= 100 && l_nResponseCode < 400 ) { invokeCallback( in_pSMTP->smtpSink, in_callback, l_nResponseCode, &(in_pSMTP->responseLine[4]) ); } else if ( l_nResponseCode >= 400 && l_nResponseCode < 600 ) { invokeCallback( in_pSMTP->smtpSink, in_pSMTP->smtpSink->error, l_nResponseCode, &(in_pSMTP->responseLine[4]) ); } else { return NSMAIL_ERR_UNEXPECTED; } return NSMAIL_OK; } static int parseMultiLine( smtpClient_t * in_pSMTP, sinkMethod_t in_callback, sinkMethodComplete_t in_callbackComplete ) { /* The 3-digit response code. */ int l_nResponseCode; int l_nReturnCode; do { /* Read the next line of data from the socket. */ l_nReturnCode = IO_readLine( &(in_pSMTP->io), in_pSMTP->responseLine, 512 ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } /* Parse out the response code and the message. */ l_nReturnCode = setStatusInfo( in_pSMTP->responseLine, &l_nResponseCode ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } if ( l_nResponseCode >= 100 && l_nResponseCode < 400 ) { invokeCallback( in_pSMTP->smtpSink, in_callback, l_nResponseCode, &(in_pSMTP->responseLine[4]) ); } else if ( l_nResponseCode >= 400 && l_nResponseCode < 600 ) { invokeCallback( in_pSMTP->smtpSink, in_pSMTP->smtpSink->error, l_nResponseCode, &(in_pSMTP->responseLine[4]) ); } else { return NSMAIL_ERR_UNEXPECTED; } } while( in_pSMTP->responseLine[3] == '-' ); /* Invoke the callback. */ if ( in_callbackComplete != NULL ) { in_callbackComplete(in_pSMTP->smtpSink); } return NSMAIL_OK; } static int parseData( smtpClient_t * in_pSMTP ) { /* The 3-digit response code. */ int l_nResponseCode; /* Read the next line of data from the socket. */ int l_nReturnCode = IO_readLine( &(in_pSMTP->io), in_pSMTP->responseLine, 512 ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } /* Parse out the response code and the message. */ l_nReturnCode = setStatusInfo( in_pSMTP->responseLine, &l_nResponseCode ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } if ( l_nResponseCode >= 100 && l_nResponseCode < 400 ) { invokeCallback( in_pSMTP->smtpSink, in_pSMTP->smtpSink->data, l_nResponseCode, &(in_pSMTP->responseLine[4]) ); in_pSMTP->fDATASent = TRUE; } else if ( l_nResponseCode >= 400 && l_nResponseCode < 600 ) { invokeCallback( in_pSMTP->smtpSink, in_pSMTP->smtpSink->error, l_nResponseCode, &(in_pSMTP->responseLine[4]) ); } else { return NSMAIL_ERR_UNEXPECTED; } return NSMAIL_OK; } static int parseEhlo( smtpClient_t * in_pSMTP ) { /* The 3-digit response code. */ int l_nResponseCode; int l_nReturnCode; do { /* Read the next line of data from the socket. */ l_nReturnCode = IO_readLine( &(in_pSMTP->io), in_pSMTP->responseLine, 512 ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } /* Parse out the response code and the message. */ l_nReturnCode = setStatusInfo( in_pSMTP->responseLine, &l_nResponseCode ); if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } /* Determine if PIPELINING is supported by the server. */ if ( in_pSMTP->pipelining == FALSE ) { if (strncmp(pipelining, &(in_pSMTP->responseLine[4]), 10) == 0) { in_pSMTP->pipeliningSupported = TRUE; } } if ( l_nReturnCode != NSMAIL_OK ) { return l_nReturnCode; } if ( l_nResponseCode >= 100 && l_nResponseCode < 400 ) { invokeCallback( in_pSMTP->smtpSink, in_pSMTP->smtpSink->ehlo, l_nResponseCode, &(in_pSMTP->responseLine[4]) ); } else if ( l_nResponseCode >= 400 && l_nResponseCode < 600 ) { invokeCallback( in_pSMTP->smtpSink, in_pSMTP->smtpSink->error, l_nResponseCode, &(in_pSMTP->responseLine[4]) ); } else { return NSMAIL_ERR_UNEXPECTED; } } while( in_pSMTP->responseLine[3] == '-' ); /* Invoke the callback. */ if ( in_pSMTP->smtpSink->ehloComplete != NULL ) { in_pSMTP->smtpSink->ehloComplete(in_pSMTP->smtpSink); } return NSMAIL_OK; } static void invokeCallback( smtpSink_t * in_pSMTPSink, sinkMethod_t in_callback, int in_responseCode, const char * in_responseMessage ) { if ( in_callback != NULL ) { in_callback( in_pSMTPSink, in_responseCode, in_responseMessage ); } } /* Initializes and allocates the smtpSink_t structure. */ int smtpSink_initialize( smtpSink_t ** out_ppSMTPSink ) { /* Parameter validation. */ if ( out_ppSMTPSink == NULL || (*out_ppSMTPSink) != NULL ) { return NSMAIL_ERR_INVALIDPARAM; } /* Create the sink */ (*out_ppSMTPSink) = (smtpSink_t*)malloc( sizeof(smtpSink_t) ); if ( (*out_ppSMTPSink) == NULL ) { return NSMAIL_ERR_OUTOFMEMORY; } memset( (*out_ppSMTPSink), 0, sizeof(smtpSink_t) ); return NSMAIL_OK; } /* Function used to free the smtpSink_t structure. */ void smtpSink_free( smtpSink_t ** in_ppSMTPSink ) { if ( in_ppSMTPSink == NULL || *in_ppSMTPSink == NULL ) { return; } /* Free the sink. */ free( *in_ppSMTPSink ); *in_ppSMTPSink = NULL; } #ifdef SMTP_HIGHLEVEL_API /* * A higher level API * @author derekt@netscape.com * @version 1.0 */ void sinkError( smtpSinkPtr_t in_pSMTPSink, int in_responseCode, const char * in_errorMessage ) { returnInfo_t * l_pReturnInfo = (returnInfo_t*)in_pSMTPSink->pOpaqueData; l_pReturnInfo->error = TRUE; strncpy( (char*)&(l_pReturnInfo->errorBuffer), in_errorMessage, 512 ); } int smtp_sendMessage( const char * in_server, const char * in_domain, const char * in_sender, const char * in_recipients, const char * in_message, char * out_serverError ) { int l_nReturn; char l_delim = ','; smtpClient_t * l_pClient = NULL; smtpSink_t * l_pSink = NULL; char * l_pRecipient1; char * l_pRecipient2; char l_recipient[256]; returnInfo_t l_returnInfo; /* Check for invalid parameters. */ if ( in_server == NULL || in_domain == NULL || in_sender == NULL || in_recipients == NULL || in_message == NULL ) { return NSMAIL_ERR_INVALIDPARAM; } if ( out_serverError != NULL ) { out_serverError[0] = '\0'; } /* Initialize the response sink. */ l_nReturn = smtpSink_initialize( &l_pSink ); if ( l_nReturn != NSMAIL_OK ) { return l_nReturn; } l_pSink->error = sinkError; l_returnInfo.error = FALSE; memset( &(l_returnInfo.errorBuffer), 0, 512 * sizeof(char) ); l_pSink->pOpaqueData = &l_returnInfo; /* Initialize the client. */ l_nReturn = smtp_initialize( &l_pClient, l_pSink ); if ( l_nReturn != NSMAIL_OK ) { free( l_pSink->pOpaqueData ); smtpSink_free( &l_pSink ); return l_nReturn; } /* Connect to the server. */ l_nReturn = smtp_connect( l_pClient, in_server, 25 ); if ( l_nReturn != NSMAIL_OK ) { cleanup( l_pClient, l_pSink ); return l_nReturn; } l_nReturn = smtp_processResponses( l_pClient ); if ( l_nReturn != NSMAIL_OK ) { cleanup( l_pClient, l_pSink ); return l_nReturn; } else if ( ((returnInfo_t*)l_pSink->pOpaqueData)->error == TRUE ) { cleanupServerError( l_pClient, l_pSink, out_serverError ); return NSMAIL_ERR_PARSE; } /* Send the EHLO command. */ l_nReturn = smtp_ehlo( l_pClient, in_domain ); if ( l_nReturn != NSMAIL_OK ) { cleanup( l_pClient, l_pSink ); return l_nReturn; } l_nReturn = smtp_processResponses( l_pClient ); if ( l_nReturn != NSMAIL_OK ) { cleanup( l_pClient, l_pSink ); return l_nReturn; } else if ( ((returnInfo_t*)l_pSink->pOpaqueData)->error == TRUE ) { cleanupServerError( l_pClient, l_pSink, out_serverError ); return NSMAIL_ERR_PARSE; } /* Send the MAIL FROM command. */ l_nReturn = smtp_mailFrom( l_pClient, in_sender, NULL ); if ( l_nReturn != NSMAIL_OK ) { cleanup( l_pClient, l_pSink ); return l_nReturn; } l_nReturn = smtp_processResponses( l_pClient ); if ( l_nReturn != NSMAIL_OK ) { cleanup( l_pClient, l_pSink ); return l_nReturn; } else if ( ((returnInfo_t*)l_pSink->pOpaqueData)->error == TRUE ) { cleanupServerError( l_pClient, l_pSink, out_serverError ); return NSMAIL_ERR_PARSE; } l_pRecipient1 = (char*)in_recipients; while( (l_pRecipient2 = strchr( l_pRecipient1, l_delim )) != NULL ) { l_pRecipient2[0] = '\0'; if ( strlen(l_pRecipient2) > 256 ) { cleanup( l_pClient, l_pSink ); return NSMAIL_ERR_PARSE; } strncpy( l_recipient, l_pRecipient1, 256 ); l_pRecipient2[0] = ','; /* Send the RCPT TO command. */ l_nReturn = smtp_rcptTo( l_pClient, l_recipient, NULL ); if ( l_nReturn != NSMAIL_OK ) { cleanup( l_pClient, l_pSink ); return l_nReturn; } l_nReturn = smtp_processResponses( l_pClient ); if ( l_nReturn != NSMAIL_OK ) { cleanup( l_pClient, l_pSink ); return l_nReturn; } else if ( ((returnInfo_t*)l_pSink->pOpaqueData)->error == TRUE ) { cleanupServerError( l_pClient, l_pSink, out_serverError ); return NSMAIL_ERR_PARSE; } l_pRecipient1 = &(l_pRecipient2[1]); } /* Move ahead past the white space. */ while ( *l_pRecipient1 == ' ' || *l_pRecipient1 == '\t' ) { l_pRecipient1 = &(l_pRecipient1[1]); } /* See if it is the end. */ if ( strlen( l_pRecipient1 ) != 0 ) { /* Send the RCPT TO command. */ l_nReturn = smtp_rcptTo( l_pClient, l_pRecipient1, NULL ); if ( l_nReturn != NSMAIL_OK ) { cleanup( l_pClient, l_pSink ); return l_nReturn; } l_nReturn = smtp_processResponses( l_pClient ); if ( l_nReturn != NSMAIL_OK ) { cleanup( l_pClient, l_pSink ); return l_nReturn; } else if ( ((returnInfo_t*)l_pSink->pOpaqueData)->error == TRUE ) { cleanupServerError( l_pClient, l_pSink, out_serverError ); return NSMAIL_ERR_PARSE; } } /* Send the DATA command. */ l_nReturn = smtp_data( l_pClient ); if ( l_nReturn != NSMAIL_OK ) { cleanup( l_pClient, l_pSink ); return l_nReturn; } l_nReturn = smtp_processResponses( l_pClient ); if ( l_nReturn != NSMAIL_OK ) { cleanup( l_pClient, l_pSink ); return l_nReturn; } else if ( ((returnInfo_t*)l_pSink->pOpaqueData)->error == TRUE ) { cleanupServerError( l_pClient, l_pSink, out_serverError ); return NSMAIL_ERR_PARSE; } /* Send the message. */ l_nReturn = smtp_send( l_pClient, in_message ); if ( l_nReturn != NSMAIL_OK ) { cleanup( l_pClient, l_pSink ); return l_nReturn; } l_nReturn = smtp_processResponses( l_pClient ); if ( l_nReturn != NSMAIL_OK ) { cleanup( l_pClient, l_pSink ); return l_nReturn; } else if ( ((returnInfo_t*)l_pSink->pOpaqueData)->error == TRUE ) { cleanupServerError( l_pClient, l_pSink, out_serverError ); return NSMAIL_ERR_PARSE; } /* Disconnect from the server. */ l_nReturn = smtp_quit( l_pClient ); if ( l_nReturn != NSMAIL_OK ) { cleanup( l_pClient, l_pSink ); return l_nReturn; } l_nReturn = smtp_processResponses( l_pClient ); if ( l_nReturn != NSMAIL_OK ) { cleanup( l_pClient, l_pSink ); return l_nReturn; } else if ( ((returnInfo_t*)l_pSink->pOpaqueData)->error == TRUE ) { cleanupServerError( l_pClient, l_pSink, out_serverError ); return NSMAIL_ERR_PARSE; } cleanup( l_pClient, l_pSink ); return NSMAIL_OK; } int smtp_sendMessageStream( const char * in_server, const char * in_domain, const char * in_sender, const char * in_recipients, nsmail_inputstream_t * in_inputStream, char * out_serverError ) { int l_nReturn; char l_delim = ','; smtpClient_t * l_pClient = NULL; smtpSink_t * l_pSink = NULL; char * l_pRecipient1; char * l_pRecipient2; char l_recipient[256]; returnInfo_t l_returnInfo; /* Check for invalid parameters. */ if ( in_server == NULL || in_domain == NULL || in_sender == NULL || in_recipients == NULL || in_inputStream == NULL ) { return NSMAIL_ERR_INVALIDPARAM; } if ( out_serverError != NULL ) { out_serverError[0] = '\0'; } /* Initialize the response sink. */ l_nReturn = smtpSink_initialize( &l_pSink ); if ( l_nReturn != NSMAIL_OK ) { return l_nReturn; } l_pSink->error = sinkError; l_returnInfo.error = FALSE; memset( &(l_returnInfo.errorBuffer), 0, 512 * sizeof(char) ); l_pSink->pOpaqueData = &l_returnInfo; /* Initialize the client. */ l_nReturn = smtp_initialize( &l_pClient, l_pSink ); if ( l_nReturn != NSMAIL_OK ) { free( l_pSink->pOpaqueData ); smtpSink_free( &l_pSink ); return l_nReturn; } /* Connect to the server. */ l_nReturn = smtp_connect( l_pClient, in_server, 25 ); if ( l_nReturn != NSMAIL_OK ) { cleanup( l_pClient, l_pSink ); return l_nReturn; } l_nReturn = smtp_processResponses( l_pClient ); if ( l_nReturn != NSMAIL_OK ) { cleanup( l_pClient, l_pSink ); return l_nReturn; } else if ( ((returnInfo_t*)l_pSink->pOpaqueData)->error == TRUE ) { cleanupServerError( l_pClient, l_pSink, out_serverError ); return NSMAIL_ERR_PARSE; } /* Send the EHLO command. */ l_nReturn = smtp_ehlo( l_pClient, in_domain ); if ( l_nReturn != NSMAIL_OK ) { cleanup( l_pClient, l_pSink ); return l_nReturn; } l_nReturn = smtp_processResponses( l_pClient ); if ( l_nReturn != NSMAIL_OK ) { cleanup( l_pClient, l_pSink ); return l_nReturn; } else if ( ((returnInfo_t*)l_pSink->pOpaqueData)->error == TRUE ) { cleanupServerError( l_pClient, l_pSink, out_serverError ); return NSMAIL_ERR_PARSE; } /* Send the MAIL FROM command. */ l_nReturn = smtp_mailFrom( l_pClient, in_sender, NULL ); if ( l_nReturn != NSMAIL_OK ) { cleanup( l_pClient, l_pSink ); return l_nReturn; } l_nReturn = smtp_processResponses( l_pClient ); if ( l_nReturn != NSMAIL_OK ) { cleanup( l_pClient, l_pSink ); return l_nReturn; } else if ( ((returnInfo_t*)l_pSink->pOpaqueData)->error == TRUE ) { cleanupServerError( l_pClient, l_pSink, out_serverError ); return NSMAIL_ERR_PARSE; } l_pRecipient1 = (char*)in_recipients; while( (l_pRecipient2 = strchr( l_pRecipient1, l_delim )) != NULL ) { l_pRecipient2[0] = '\0'; if ( strlen(l_pRecipient2) > 256 ) { cleanup( l_pClient, l_pSink ); return NSMAIL_ERR_PARSE; } strncpy( l_recipient, l_pRecipient1, 256 ); l_pRecipient2[0] = ','; /* Send the RCPT TO command. */ l_nReturn = smtp_rcptTo( l_pClient, l_recipient, NULL ); if ( l_nReturn != NSMAIL_OK ) { cleanup( l_pClient, l_pSink ); return l_nReturn; } l_nReturn = smtp_processResponses( l_pClient ); if ( l_nReturn != NSMAIL_OK ) { cleanup( l_pClient, l_pSink ); return l_nReturn; } else if ( ((returnInfo_t*)l_pSink->pOpaqueData)->error == TRUE ) { cleanupServerError( l_pClient, l_pSink, out_serverError ); return NSMAIL_ERR_PARSE; } l_pRecipient1 = &(l_pRecipient2[1]); } /* Move ahead past the white space. */ while ( *l_pRecipient1 == ' ' || *l_pRecipient1 == '\t' ) { l_pRecipient1 = &(l_pRecipient1[1]); } /* See if it is the end. */ if ( strlen( l_pRecipient1 ) != 0 ) { /* Send the RCPT TO command. */ l_nReturn = smtp_rcptTo( l_pClient, l_pRecipient1, NULL ); if ( l_nReturn != NSMAIL_OK ) { cleanup( l_pClient, l_pSink ); return l_nReturn; } l_nReturn = smtp_processResponses( l_pClient ); if ( l_nReturn != NSMAIL_OK ) { cleanup( l_pClient, l_pSink ); return l_nReturn; } else if ( ((returnInfo_t*)l_pSink->pOpaqueData)->error == TRUE ) { cleanupServerError( l_pClient, l_pSink, out_serverError ); return NSMAIL_ERR_PARSE; } } /* Send the DATA command. */ l_nReturn = smtp_data( l_pClient ); if ( l_nReturn != NSMAIL_OK ) { cleanup( l_pClient, l_pSink ); return l_nReturn; } l_nReturn = smtp_processResponses( l_pClient ); if ( l_nReturn != NSMAIL_OK ) { cleanup( l_pClient, l_pSink ); return l_nReturn; } else if ( ((returnInfo_t*)l_pSink->pOpaqueData)->error == TRUE ) { cleanupServerError( l_pClient, l_pSink, out_serverError ); return NSMAIL_ERR_PARSE; } /* Send the message. */ l_nReturn = smtp_sendStream( l_pClient, in_inputStream ); if ( l_nReturn != NSMAIL_OK ) { cleanup( l_pClient, l_pSink ); return l_nReturn; } l_nReturn = smtp_processResponses( l_pClient ); if ( l_nReturn != NSMAIL_OK ) { cleanup( l_pClient, l_pSink ); return l_nReturn; } else if ( ((returnInfo_t*)l_pSink->pOpaqueData)->error == TRUE ) { cleanupServerError( l_pClient, l_pSink, out_serverError ); return NSMAIL_ERR_PARSE; } /* Disconnect from the server. */ l_nReturn = smtp_quit( l_pClient ); if ( l_nReturn != NSMAIL_OK ) { cleanup( l_pClient, l_pSink ); return l_nReturn; } l_nReturn = smtp_processResponses( l_pClient ); if ( l_nReturn != NSMAIL_OK ) { cleanup( l_pClient, l_pSink ); return l_nReturn; } else if ( ((returnInfo_t*)l_pSink->pOpaqueData)->error == TRUE ) { cleanupServerError( l_pClient, l_pSink, out_serverError ); return NSMAIL_ERR_PARSE; } cleanup( l_pClient, l_pSink ); return NSMAIL_OK; } void cleanup( smtpClient_t * in_pClient, smtpSink_t * in_pSink ) { smtp_free( &in_pClient ); smtpSink_free( &in_pSink ); } void cleanupServerError( smtpClient_t * in_pClient, smtpSink_t * in_pSink, char * out_serverError ) { if ( out_serverError != NULL ) { strncpy( out_serverError, (char*)&(((returnInfo_t*)in_pSink->pOpaqueData)->errorBuffer), 512 ); } smtp_free( &in_pClient ); smtpSink_free( &in_pSink ); } #endif /*SMTP_HIGHLEVEL_API*/