Skip to content

Commit

Permalink
HPCC-30377 SendEmail exception while reading from mail server 2
Browse files Browse the repository at this point in the history
Signed-off-by: Mark Kelly <[email protected]>
  • Loading branch information
mckellyln committed Nov 2, 2023
1 parent 2d4d669 commit d425d0b
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 70 deletions.
98 changes: 38 additions & 60 deletions common/remote/rmtsmtp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -530,16 +530,6 @@ class CMailInfo
else
lastAction.clear().append(len, out).clip();

// read any remaining bytes ...
try
{
socket->readtms(inbuff, 0, sizeof(inbuff), inlen, 0);
}
catch(IException * e)
{
e->Release();
}

try
{
socket->write(out, len);
Expand All @@ -557,14 +547,14 @@ class CMailInfo
}
}

bool read(int keepTrying)
bool read(int numRetriesRemaining)
{
try
{
socket->readtms(inbuff, 1, sizeof(inbuff), inlen, 30000);

//MORE: the following is somewhat primitive and not RFC compliant (see bug 25951) - but it is a lot better than nothing
if ( (*inbuff == '5') || ((*inbuff == '4') && (!keepTrying)) )
if ( (*inbuff == '5') || ((*inbuff == '4') && (!numRetriesRemaining)) )
{
StringBuffer b;
b.append("negative reply after writing ").append(inlen, inbuff).clip();
Expand Down Expand Up @@ -594,6 +584,34 @@ class CMailInfo
}
}

void readRemainingData()
{
// read any remaining bytes ...
try
{
socket->readtms(inbuff, 0, sizeof(inbuff), inlen, 0);
}
catch(IException * e)
{
e->Release();
}
}

void writeAndAck(char const * out, size32_t len, char const * action = NULL)
{
bool ok;
int retries = 2;
while (retries >= 0)
{
readRemainingData();
write(out, len, action);
ok = read(retries);
if (ok)
break;
retries--;
}
}

void getHeader(StringBuffer & header) const
{
header.append(senderHeader).append(sender.get()).append("\r\n");
Expand Down Expand Up @@ -808,62 +826,30 @@ static void doSendEmail(CMailInfo & info, CMailPart const & part)
info.read(0);
info.getHelo(outbuff);

bool ok;
int retries = 2;
while (retries >= 0)
{
info.write(outbuff.str(), outbuff.length());
ok = info.read(retries);
if (ok)
break;
retries--;
}
info.writeAndAck(outbuff.str(), outbuff.length());

info.getMailFrom(outbuff.clear());

retries = 2;
while (retries >= 0)
{
info.write(outbuff.str(), outbuff.length());
ok = info.read(retries);
if (ok)
break;
retries--;
}
info.writeAndAck(outbuff.str(), outbuff.length());

unsigned numRcpt = info.numRecipients();
for(unsigned i=0; i<numRcpt; ++i)
{
info.getRecipient(i, outbuff.clear());

retries = 2;
while (retries >= 0)
{
info.write(outbuff.str(), outbuff.length());
ok = info.read(retries);
if (ok)
break;
retries--;
}
info.writeAndAck(outbuff.str(), outbuff.length());
}

retries = 2;
while (retries >= 0)
{
info.write(data, strlen(data));
ok = info.read(retries);
if (ok)
break;
retries--;
}
info.writeAndAck(data, strlen(data));

info.getHeader(outbuff.clear());
part.getHeader(outbuff);
outbuff.append("\r\n");

retries = 2;
bool ok;
int retries = 2;
while (retries >= 0)
{
info.readRemainingData();
info.write(outbuff.str(), outbuff.length(), "mail header");
part.write(info);
info.write(endMail, strlen(endMail), "end of mail body");
Expand All @@ -873,15 +859,7 @@ static void doSendEmail(CMailInfo & info, CMailPart const & part)
retries--;
}

retries = 2;
while (retries >= 0)
{
info.write(quit, strlen(quit));
ok = info.read(retries);
if (ok)
break;
retries--;
}
info.writeAndAck(quit, strlen(quit));
}
catch(IException * e)
{
Expand Down
15 changes: 9 additions & 6 deletions ecllibrary/std/system/Email.ecl
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@ RETURN MODULE
* @param cc Optional comma-delimited addresses of carbon-copy recipients. Defaults to an empty string (none).
* @param bcc Optional comma-delimited addresses of blind-carbon-copy recipients. Defaults to an empty string (none).
* @param highPriority Optional; if true, message is sent with high priority. Defaults to false (normal priority).
* @param rptErrAsFail Optional; if true, any error while trying to send email will result in an error/exception. Defaults to true.
*/

EXPORT SendEmail(varstring to, varstring subject, varstring body, varstring mailServer=GETENV('SMTPserver'), unsigned4 port=(unsigned4) GETENV('SMTPport', '25'), varstring sender=GETENV('emailSenderAddress'), varstring cc='', varstring bcc='', boolean highPriority=false, boolean termJobOnFail=true) :=
lib_fileservices.FileServices.SendEmail(to, subject, body, mailServer, port, sender, cc, bcc, highPriority, termJobOnFail);
EXPORT SendEmail(varstring to, varstring subject, varstring body, varstring mailServer=GETENV('SMTPserver'), unsigned4 port=(unsigned4) GETENV('SMTPport', '25'), varstring sender=GETENV('emailSenderAddress'), varstring cc='', varstring bcc='', boolean highPriority=false, boolean rptErrAsFail=true) :=
lib_fileservices.FileServices.SendEmail(to, subject, body, mailServer, port, sender, cc, bcc, highPriority, rptErrAsFail);

/*
* Sends an email message with a text attachment using a mail server.
Expand All @@ -36,10 +37,11 @@ EXPORT SendEmail(varstring to, varstring subject, varstring body, varstring mail
* @param cc Optional comma-delimited addresses of carbon-copy recipients. Defaults to an empty string (none).
* @param bcc Optional comma-delimited addresses of blind-carbon-copy recipients. Defaults to an empty string (none).
* @param highPriority Optional; if true, message is sent with high priority. Defaults to false (normal priority).
* @param rptErrAsFail Optional; if true, any error while trying to send email will result in an error/exception. Defaults to true.
*/

EXPORT SendEmailAttachText(varstring to, varstring subject, varstring body, varstring attachment, varstring mimeType, varstring attachmentName, varstring mailServer=GETENV('SMTPserver'), unsigned4 port=(unsigned4) GETENV('SMTPport', '25'), varstring sender=GETENV('emailSenderAddress'), varstring cc='', varstring bcc='', boolean highPriority=false, boolean termJobOnFail=true) :=
lib_fileservices.FileServices.SendEmailAttachText(to, subject, body, attachment, mimeType, attachmentName, mailServer, port, sender, cc, bcc, highPriority, termJobOnFail);
EXPORT SendEmailAttachText(varstring to, varstring subject, varstring body, varstring attachment, varstring mimeType, varstring attachmentName, varstring mailServer=GETENV('SMTPserver'), unsigned4 port=(unsigned4) GETENV('SMTPport', '25'), varstring sender=GETENV('emailSenderAddress'), varstring cc='', varstring bcc='', boolean highPriority=false, boolean rptErrAsFail=true) :=
lib_fileservices.FileServices.SendEmailAttachText(to, subject, body, attachment, mimeType, attachmentName, mailServer, port, sender, cc, bcc, highPriority, rptErrAsFail);

/*
* Sends an email message with an arbitrary attachment using a mail server.
Expand All @@ -56,9 +58,10 @@ EXPORT SendEmailAttachText(varstring to, varstring subject, varstring body, vars
* @param cc Optional comma-delimited addresses of carbon-copy recipients. Defaults to an empty string (none).
* @param bcc Optional comma-delimited addresses of blind-carbon-copy recipients. Defaults to an empty string (none).
* @param highPriority Optional; if true, message is sent with high priority. Defaults to false (normal priority).
* @param rptErrAsFail Optional; if true, any error while trying to send email will result in an error/exception. Defaults to true.
*/

EXPORT SendEmailAttachData(varstring to, varstring subject, varstring body, data attachment, varstring mimeType, varstring attachmentName, varstring mailServer=GETENV('SMTPserver'), unsigned4 port=(unsigned4) GETENV('SMTPport', '25'), varstring sender=GETENV('emailSenderAddress'), varstring cc='', varstring bcc='', boolean highPriority=false, boolean termJobOnFail=true) :=
lib_fileservices.FileServices.SendEmailAttachData(to, subject, body, attachment, mimeType, attachmentName, mailServer, port, sender, cc, bcc, highPriority, termJobOnFail);
EXPORT SendEmailAttachData(varstring to, varstring subject, varstring body, data attachment, varstring mimeType, varstring attachmentName, varstring mailServer=GETENV('SMTPserver'), unsigned4 port=(unsigned4) GETENV('SMTPport', '25'), varstring sender=GETENV('emailSenderAddress'), varstring cc='', varstring bcc='', boolean highPriority=false, boolean rptErrAsFail=true) :=
lib_fileservices.FileServices.SendEmailAttachData(to, subject, body, attachment, mimeType, attachmentName, mailServer, port, sender, cc, bcc, highPriority, rptErrAsFail);

END;
5 changes: 1 addition & 4 deletions plugins/fileservices/fileservices.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -533,10 +533,7 @@ FILESERVICES_API void FILESERVICES_CALL fsSendEmail_v3(ICodeContext * ctx, const

FILESERVICES_API void FILESERVICES_CALL fsSendEmail_v2(ICodeContext * ctx, const char * to, const char * subject, const char * body, const char * mailServer, unsigned port, const char * sender, const char *cc, const char *bcc, bool highPriority)
{
StringArray warnings;
sendEmail( to, cc, bcc, subject, body, mailServer, port, sender, &warnings, highPriority, true);
ForEachItemIn(i,warnings)
WUmessage(ctx, SeverityWarning, "SendEmail", warnings.item(i));
fsSendEmail_v3(ctx, to, subject, body, mailServer, port, sender, cc, bcc, highPriority, true);
}

FILESERVICES_API void FILESERVICES_CALL fsSendEmail(ICodeContext * ctx, const char * to, const char * subject, const char * body, const char * mailServer, unsigned port, const char * sender)
Expand Down

0 comments on commit d425d0b

Please sign in to comment.