| Return Type | Function name | Arguments |
|---|---|---|
| hzEcode | hzEmail::SendSmtp | (const char*,const char*,const char*,) |
Declared in file: hzMailer.h
Defined in file : hzMailer.cpp
Function Logic:
Function body:
hzEcode hzEmail::SendSmtp (const char* server, const char* uname, const char* passwd)
{
_hzfunc("hzEmail::SendSmtp") ;
hzList<hzEmaddr>::Iter rx ;
hzTcpClient C ;
hzChain inp ;
hzChain oup ;
chIter ci ;
hzLogger* plog ;
char* i ;
hzString S ;
hzEmaddr e ;
uint32_t nRecv ;
uint32_t nSend ;
uint32_t nTotal = 0;
char sbuf[HZ_MAXPACKET+4];
char rbuf[HZ_MAXPACKET+4];
SMTPCode smtpCode ;
hzEcode rc = E_OK ;
plog = GetThreadLogger() ;
if (!plog)
Fatal("No thread logger\n") ;
if (!server || !server[0]) { rc = E_ARGUMENT ; plog->Out("No SMTP server supplied\n") ; }
if (!uname || !uname[0]){ rc = E_ARGUMENT ; plog->Out("No SMTP username supplied\n") ; }
if (!passwd || !passwd[0]) { rc = E_ARGUMENT ; plog->Out("No SMTP password supplied\n") ; }
if (!m_Recipients.Count()) { rc = E_ARGUMENT ; plog->Out("No recipients specified\n") ; }
if (!m_AddrFrom) { rc = E_ARGUMENT ; plog->Out("No sender address specified\n") ; }
if (rc != E_OK)
return rc ;
if (!m_RealFrom)
m_RealFrom = *m_AddrFrom ;
S = server ;
rc = C.ConnectStd(S, 25);
if (rc != E_OK)
{
hzerr(rc, "Could not conect to SMTP server [%s]", server) ;
return rc ;
}
C.Recv(rbuf, nRecv, HZ_MAXPACKET) ;
if (nRecv >&eq; 0)
rbuf[nRecv] = 0;
else
rbuf[0]= 0;
smtpCode = _getSmtpCode(rbuf) ;
if (smtpCode != SMTP_READY)
{
plog->Out("%d Server not ready so quiting\n", smtpCode) ;
rc = E_HOSTRETRY ;
goto Quit ;
}
sprintf(sbuf, "EHLO %s\r\n", *m_AddrFrom) ;
if ((rc = C.Send(sbuf, strlen(sbuf))) != E_OK)
{
plog->Out("Could not send HELO command\n") ;
goto Quit ;
}
if (_hzGlobal_Debug & HZ_DEBUG_MAILER)
plog->Out("Client -> %s", sbuf) ;
if ((rc = C.Recv(rbuf, nRecv, HZ_MAXPACKET)) != E_OK)
{
plog->Out("Could not get ACK to EHLO msg\n") ;
goto Quit ;
}
if (nRecv >&eq; 0)
rbuf[nRecv] = 0;
else
rbuf[0]= 0;
smtpCode = _getSmtpCode(rbuf) ;
if (smtpCode != SMTP_OK)
{ rc = E_PROTOCOL ; plog->Out("Expected ACK so quitting\n") ; goto Quit ; }
if (_hzGlobal_Debug & HZ_DEBUG_MAILER)
plog->Out("Server -> %s\n", rbuf) ;
if (uname && passwd)
{
if (_hzGlobal_Debug & HZ_DEBUG_MAILER)
plog->Out("Have username of %s and password of %s so will auth\n", uname, passwd) ;
strcpy(sbuf, "AUTH LOGIN\r\n") ;
if ((rc = C.Send(sbuf, strlen(sbuf))) != E_OK)
{ plog->Out("Could not send MAIL FROM message\n") ; goto Quit ; }
if (_hzGlobal_Debug & HZ_DEBUG_MAILER)
plog->Out("Client -> %s", sbuf) ;
C.Recv(rbuf, nRecv, HZ_MAXPACKET) ;
if (nRecv > 0)
rbuf[nRecv] = 0;
else
rbuf[0]= 0;
smtpCode = _getSmtpCode(rbuf) ;
if (_hzGlobal_Debug & HZ_DEBUG_MAILER)
plog->Out("Server -> %s", rbuf) ;
if (smtpCode != SMTP_LOGINFO)
{ rc = E_BADSENDER ; plog->Out("Expected code 334. Got instead code %d\n", smtpCode) ; goto Quit ; }
inp.Clear() ;
oup.Clear() ;
inp = uname ;
Base64Encode(oup, inp) ;
oup << "\r\n" ;
S = oup ;
if ((rc = C.Send(*S, S.Length())) != E_OK)
{ plog->Out("Could not send username\n") ; goto Quit ; }
if (_hzGlobal_Debug & HZ_DEBUG_MAILER)
plog->Out("Client -> %s", *S) ;
C.Recv(rbuf, nRecv, HZ_MAXPACKET) ;
if (nRecv > 0)
rbuf[nRecv] = 0;
else
rbuf[0]= 0;
if (_hzGlobal_Debug & HZ_DEBUG_MAILER)
plog->Out("Server -> %s", rbuf) ;
smtpCode = _getSmtpCode(rbuf) ;
if (smtpCode != SMTP_LOGINFO)
{
plog->Out("Expected code 334 (request for password). Got %d\n", smtpCode) ;
rc = E_BADSENDER ;
goto Quit ;
}
inp.Clear() ;
oup.Clear() ;
inp = passwd ;
Base64Encode(oup, inp) ;
oup << "\r\n" ;
S = oup ;
if ((rc = C.Send(*S, S.Length())) != E_OK)
{ plog->Out("Could not send password\n") ; goto Quit ; }
if (_hzGlobal_Debug & HZ_DEBUG_MAILER)
plog->Out("Client -> %s", *S) ;
C.Recv(rbuf, nRecv, HZ_MAXPACKET) ;
if (nRecv > 0)
rbuf[nRecv] = 0;
else
rbuf[0]= 0;
if (_hzGlobal_Debug & HZ_DEBUG_MAILER)
plog->Out("Server -> %s", rbuf) ;
smtpCode = _getSmtpCode(rbuf) ;
if (smtpCode != SMTP_GO_AHEAD)
{
plog->Out("Expected code 235 (Login OK, Go Ahead). Got %d\n", smtpCode) ;
rc = E_BADSENDER ;
goto Quit ;
}
}
/*
** ** Now send the sender details
** */
sprintf(sbuf, "MAIL FROM: <%s>\r\n", *m_AddrFrom) ;
if ((rc = C.Send(sbuf, strlen(sbuf))) != E_OK)
{ plog->Out("Could not send MAIL FROM message\n") ; goto Quit ; }
if (_hzGlobal_Debug & HZ_DEBUG_MAILER)
plog->Out("Client -> %s", sbuf) ;
C.Recv(rbuf, nRecv, HZ_MAXPACKET) ;
if (nRecv > 0)
rbuf[nRecv] = 0;
else
rbuf[0]= 0;
if (_hzGlobal_Debug & HZ_DEBUG_MAILER)
plog->Out("Server -> %s", rbuf) ;
smtpCode = _getSmtpCode(rbuf) ;
if (smtpCode != SMTP_OK)
{
plog->Out("Expected a 250 (OK) code. Got %d\n", smtpCode) ;
rc = E_BADSENDER ;
goto Quit ;
}
/*
** ** Now send the reciprient details
** */
for (rx = m_Recipients ; rx.Valid() ; rx++)
{
e = rx.Element() ;
sprintf(sbuf, "RCPT TO: <%s>\r\n", *e) ;
C.Send(sbuf, strlen(sbuf)) ;
if (_hzGlobal_Debug & HZ_DEBUG_MAILER)
plog->Out("Client -> %s", sbuf) ;
rc = C.Recv(rbuf, nRecv, HZ_MAXPACKET) ;
if (rc != E_OK)
{
plog->Out("Broken pipe while sending recipient details\n") ;
goto Quit ;
}
if (nRecv > 0)
rbuf[nRecv] = 0;
else
rbuf[0]= 0;
if (_hzGlobal_Debug & HZ_DEBUG_MAILER)
plog->Out("Server -> %s", rbuf) ;
smtpCode = _getSmtpCode(rbuf) ;
if (smtpCode != SMTP_OK && smtpCode != SMTP_GO_AHEAD)
{
plog->Out("Expected a 250 (OK) or 235 (Go Ahead) code. Got %d\n", smtpCode) ;
rc = E_NOACCOUNT ;
goto Quit ;
}
}
for (rx = m_CC ; rx.Valid() ; rx++)
{
e = rx.Element() ;
sprintf(sbuf, "RCPT TO: <%s>\r\n", *e) ;
C.Send(sbuf, strlen(sbuf)) ;
if (_hzGlobal_Debug & HZ_DEBUG_MAILER)
plog->Out("Client -> %s", sbuf) ;
rc = C.Recv(rbuf, nRecv, HZ_MAXPACKET) ;
if (rc != E_OK)
{
plog->Out("Broken pipe while sending recipient details\n") ;
goto Quit ;
}
if (nRecv > 0)
rbuf[nRecv] = 0;
else
rbuf[0]= 0;
if (_hzGlobal_Debug & HZ_DEBUG_MAILER)
plog->Out("Server -> %s", rbuf) ;
smtpCode = _getSmtpCode(rbuf) ;
if (smtpCode != SMTP_OK)
{
plog->Out("Target user not ok so quiting\n") ;
rc = E_NOACCOUNT ;
goto Quit ;
}
}
for (rx = m_BCC ; rx.Valid() ; rx++)
{
e = rx.Element() ;
sprintf(sbuf, "RCPT TO: <%s>\r\n", *e) ;
C.Send(sbuf, strlen(sbuf)) ;
if (_hzGlobal_Debug & HZ_DEBUG_MAILER)
plog->Out("Client -> %s", sbuf) ;
rc = C.Recv(rbuf, nRecv, HZ_MAXPACKET) ;
if (rc != E_OK)
{
plog->Out("Broken pipe while sending recipient details\n") ;
goto Quit ;
}
if (nRecv > 0)
rbuf[nRecv] = 0;
else
rbuf[0]= 0;
if (_hzGlobal_Debug & HZ_DEBUG_MAILER)
plog->Out("Server -> %s", rbuf) ;
smtpCode = _getSmtpCode(rbuf) ;
if (smtpCode != SMTP_OK)
{
plog->Out("Target user not ok so quiting\n") ;
rc = E_NOACCOUNT ;
goto Quit ;
}
}
sprintf(sbuf, "DATA\r\n") ;
C.Send(sbuf, strlen(sbuf)) ;
if (_hzGlobal_Debug & HZ_DEBUG_MAILER)
plog->Out("Client -> %s", sbuf) ;
C.Recv(rbuf, nRecv, HZ_MAXPACKET) ;
if (nRecv > 0)
rbuf[nRecv] = 0;
else
rbuf[0]= 0;
if (_hzGlobal_Debug & HZ_DEBUG_MAILER)
plog->Out("Server -> %s", rbuf) ;
if (_hzGlobal_Debug & HZ_DEBUG_MAILER)
plog->Out("Sending %d bytes of data\n", m_Final.Size()) ;
ci = m_Final ;
for (rc = E_OK ; rc == E_OK ;)
{
for (i = sbuf, nSend = 0; !ci.eof() && nSend < HZ_MAXPACKET ; nSend++, ci++)
*i++ = *ci ;
if (nSend == 0)
break ;
nTotal += nSend ;
rc = C.Send(sbuf, nSend) ;
}
if (_hzGlobal_Debug & HZ_DEBUG_MAILER)
plog->Out("Sent %d of %d bytes\n", nTotal, m_Final.Size()) ;
strcpy(sbuf, ".\r\n") ;
C.Send(sbuf, strlen(sbuf)) ;
if (_hzGlobal_Debug & HZ_DEBUG_MAILER)
plog->Out("Client -> %s", sbuf) ;
if (rc != E_OK)
{
plog->Out("Could not transmit msg body\n") ;
goto Quit ;
}
C.Recv(rbuf, nRecv, HZ_MAXPACKET) ;
if (nRecv > 0)
rbuf[nRecv] = 0;
else
rbuf[0]= 0;
if (_hzGlobal_Debug & HZ_DEBUG_MAILER)
plog->Out("Server -> %s", rbuf) ;
Quit:
sprintf(sbuf, "QUIT\r\n") ;
C.Send(sbuf, strlen(sbuf)) ;
if (_hzGlobal_Debug & HZ_DEBUG_MAILER)
plog->Out("Client -> %s", sbuf) ;
C.Recv(rbuf, nRecv, HZ_MAXPACKET) ;
if (nRecv > 0)
rbuf[nRecv] = 0;
else
rbuf[0]= 0;
if (_hzGlobal_Debug & HZ_DEBUG_MAILER)
plog->Out("Server -> %s", rbuf) ;
C.Close() ;
return rc ;
}