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 ; }