Bug 1195026 - improve error message on SMTP errors 5.7.0 and 5.7.1. r=mkmelin
authoraceman <acelists@atlas.sk>
Sat, 24 Nov 2018 14:01:00 +0100
changeset 32928 99fbc2409e88d794e6fe70228a92ef3bbe86856e
parent 32927 b75abd6ba2b3388ef37fc54725c02cb4eff93571
child 32929 269065e13f69fe4c65896418a7ee91ea7d20648f
push id2343
push userclokep@gmail.com
push dateMon, 10 Dec 2018 21:37:21 +0000
treeherdercomm-beta@a0750c375f71 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmkmelin
bugs1195026
Bug 1195026 - improve error message on SMTP errors 5.7.0 and 5.7.1. r=mkmelin
mail/locales/en-US/chrome/messenger/messengercompose/composeMsgs.properties
mailnews/compose/src/nsComposeStrings.cpp
mailnews/compose/src/nsComposeStrings.h
mailnews/compose/src/nsSmtpProtocol.cpp
mailnews/compose/src/nsSmtpProtocol.h
suite/locales/en-US/chrome/mailnews/compose/composeMsgs.properties
--- a/mail/locales/en-US/chrome/messenger/messengercompose/composeMsgs.properties
+++ b/mail/locales/en-US/chrome/messenger/messengercompose/composeMsgs.properties
@@ -55,24 +55,27 @@ followupToSenderMessage=The author of th
 
 ## LOCALIZATION NOTE (errorAttachingFile): argument %S is the file name/URI of the object to be attached
 errorAttachingFile=There was an error attaching %S. Please check that you have access to the file.
 
 ## LOCALIZATION NOTE (incorrectSmtpGreeting): argument %s is the Outgoing server (SMTP) greeting
 incorrectSmtpGreeting=An error occurred while sending mail: The mail server sent an incorrect greeting:  %s.
 
 ## LOCALIZATION NOTE (errorSendingRcptCommand): argument %1$S is the Outgoing server (SMTP) response, argument %2$S is the intended message recipient.
-errorSendingRcptCommand=An error occurred while sending mail. The mail server responded:  \n%1$S.\n Please check the message recipient "%2$S" and try again.
+errorSendingRcptCommand=An error occurred while sending mail. The mail server responded:\n%1$S.\nPlease check the message recipient "%2$S" and try again.
 
 ## LOCALIZATION NOTE (startTlsFailed): argument %S is the Outgoing server (SMTP)
 startTlsFailed=An error occurred while sending mail: Unable to establish a secure link with Outgoing server (SMTP) %S using STARTTLS since it doesn't advertise that feature. Switch off STARTTLS for that server or contact your service provider.
 
 ## LOCALIZATION NOTE (smtpPasswordUndefined): argument %S is the Outgoing server (SMTP) account
 smtpPasswordUndefined=An error occurred while sending mail: Could not get password for %S. The message was not sent.
 
+## LOCALIZATION NOTE (smtpSendNotAllowed): argument %s is the Outgoing server (SMTP) response
+smtpSendNotAllowed=An error occurred while sending mail. The mail server responded:\n%s.\nPlease ensure that you are using the correct identity to send and that the used authentication method is correct. Verify that you are allowed to send via this SMTP server with your current credentials from your current network.
+
 ## LOCALIZATION NOTE (smtpTempSizeExceeded): argument %s is the Outgoing server (SMTP) response
 smtpTempSizeExceeded=The size of the message you are trying to send exceeds a temporary size limit of the server. The message was not sent; try to reduce the message size or wait some time and try again. The server responded:  %s.
 
 ## LOCALIZATION NOTE (smtpPermSizeExceeded1): argument %d is the Outgoing server (SMTP) size limit
 smtpPermSizeExceeded1=The size of the message you are trying to send exceeds the global size limit (%d bytes) of the server. The message was not sent; reduce the message size and try again.
 
 ## LOCALIZATION NOTE (smtpPermSizeExceeded2): argument %s is the Outgoing server (SMTP) response
 smtpPermSizeExceeded2=The size of the message you are trying to send exceeds the global size limit of the server. The message was not sent; reduce the message size and try again. The server responded:  %s.
--- a/mailnews/compose/src/nsComposeStrings.cpp
+++ b/mailnews/compose/src/nsComposeStrings.cpp
@@ -60,16 +60,18 @@ const char* errorStringNameForErrorCode(
     case NS_ERROR_SMTP_GREETING:
       return "incorrectSmtpGreeting";
     case NS_ERROR_SENDING_RCPT_COMMAND:
       return "errorSendingRcptCommand";
     case NS_ERROR_STARTTLS_FAILED_EHLO_STARTTLS:
       return "startTlsFailed";
     case NS_ERROR_SMTP_PASSWORD_UNDEFINED:
       return "smtpPasswordUndefined";
+    case NS_ERROR_SMTP_SEND_NOT_ALLOWED:
+      return "smtpSendNotAllowed";
     case NS_ERROR_SMTP_TEMP_SIZE_EXCEEDED:
       return "smtpTempSizeExceeded";
     case NS_ERROR_SMTP_PERM_SIZE_EXCEEDED_1:
       return "smtpPermSizeExceeded1";
     case NS_ERROR_SMTP_PERM_SIZE_EXCEEDED_2:
       return "smtpPermSizeExceeded2";
     case NS_ERROR_SMTP_SEND_FAILED_UNKNOWN_SERVER:
       return "smtpSendFailedUnknownServer";
--- a/mailnews/compose/src/nsComposeStrings.h
+++ b/mailnews/compose/src/nsComposeStrings.h
@@ -41,16 +41,17 @@
 
 #define NS_ERROR_SMTP_GREETING                      NS_MSG_GENERATE_FAILURE(12572)
 
 #define NS_ERROR_SENDING_RCPT_COMMAND               NS_MSG_GENERATE_FAILURE(12575)
 
 #define NS_ERROR_STARTTLS_FAILED_EHLO_STARTTLS      NS_MSG_GENERATE_FAILURE(12582)
 
 #define NS_ERROR_SMTP_PASSWORD_UNDEFINED            NS_MSG_GENERATE_FAILURE(12584)
+#define NS_ERROR_SMTP_SEND_NOT_ALLOWED              NS_MSG_GENERATE_FAILURE(12585)
 #define NS_ERROR_SMTP_TEMP_SIZE_EXCEEDED            NS_MSG_GENERATE_FAILURE(12586)
 #define NS_ERROR_SMTP_PERM_SIZE_EXCEEDED_1          NS_MSG_GENERATE_FAILURE(12587)
 #define NS_ERROR_SMTP_PERM_SIZE_EXCEEDED_2          NS_MSG_GENERATE_FAILURE(12588)
 
 #define NS_ERROR_SMTP_SEND_FAILED_UNKNOWN_SERVER    NS_MSG_GENERATE_FAILURE(12589)
 #define NS_ERROR_SMTP_SEND_FAILED_REFUSED           NS_MSG_GENERATE_FAILURE(12590)
 #define NS_ERROR_SMTP_SEND_FAILED_INTERRUPTED       NS_MSG_GENERATE_FAILURE(12591)
 #define NS_ERROR_SMTP_SEND_FAILED_TIMEOUT           NS_MSG_GENERATE_FAILURE(12592)
--- a/mailnews/compose/src/nsSmtpProtocol.cpp
+++ b/mailnews/compose/src/nsSmtpProtocol.cpp
@@ -101,16 +101,17 @@ nsresult nsExplainErrorDetails(nsISmtpUr
 #endif
   switch (aCode)
   {
     case NS_ERROR_ILLEGAL_LOCALPART:
       bundle->GetStringFromName("errorIllegalLocalPart", eMsg);
       nsTextFormatter::ssprintf(msg, eMsg.get(), arg1, arg2);
       break;
     case NS_ERROR_SMTP_SERVER_ERROR:
+    case NS_ERROR_SMTP_SEND_NOT_ALLOWED:
     case NS_ERROR_SMTP_TEMP_SIZE_EXCEEDED:
     case NS_ERROR_SMTP_PERM_SIZE_EXCEEDED_1:
     case NS_ERROR_SMTP_PERM_SIZE_EXCEEDED_2:
     case NS_ERROR_SENDING_FROM_COMMAND:
     case NS_ERROR_SENDING_RCPT_COMMAND:
     case NS_ERROR_SENDING_DATA_COMMAND:
     case NS_ERROR_SENDING_MESSAGE:
     case NS_ERROR_SMTP_GREETING:
@@ -256,16 +257,17 @@ nsresult nsSmtpProtocol::Initialize(nsIU
         mailnewsUrl->GetStatusFeedback(getter_AddRefs(m_statusFeedback));
 
     m_dataBuf = (char *) PR_Malloc(sizeof(char) * OUTPUT_BUFFER_SIZE);
     m_dataBufSize = OUTPUT_BUFFER_SIZE;
 
     m_nextState = SMTP_START_CONNECT;
     m_nextStateAfterResponse = SMTP_START_CONNECT;
     m_responseCode = 0;
+    m_responseCodeEnhanced = 0;
     m_previousResponseCode = 0;
     m_continuationResponse = -1;
     m_tlsEnabled = false;
     m_addressesLeft = 0;
 
     m_sendDone = false;
 
     m_sizelimit = 0;
@@ -617,42 +619,55 @@ nsresult nsSmtpProtocol::SmtpResponse(ns
   {
     SetFlag(SMTP_PAUSE_FOR_READ); /* pause */
     PR_Free(line);
     return NS_OK;
   }
 
   m_totalAmountRead += ln;
 
+  // The expected response is in the format:
+  // <SMTP code><continuation char>(<optional ESMTP code> )<response text>
+  // e.g.: 123 1.2.3 Text
   MOZ_LOG(SMTPLogModule, mozilla::LogLevel::Info, ("SMTP Response: %s", line));
   cont_char = ' '; /* default */
+  int chars_read = 0;
   // sscanf() doesn't update m_responseCode if line doesn't start
   // with a number. That can be dangerous. So be sure to set
   // m_responseCode to 0 if no items read.
-  if (PR_sscanf(line, "%d%c", &m_responseCode, &cont_char) <= 0)
+  if (PR_sscanf(line, "%d%c%n", &m_responseCode, &cont_char, &chars_read) <= 0)
     m_responseCode = 0;
+  else if (cont_char != '-' )
+  {
+    m_responseCodeEnhanced = 0;
+    char codeClass, codeSubject, codeDetail;
+    if (PR_sscanf(line + chars_read, "%1u.%1u.%1u ", &codeClass, &codeSubject, &codeDetail) == 3)
+      m_responseCodeEnhanced = codeClass * 100 + codeSubject * 10 + codeDetail;
+  }
 
   if (m_continuationResponse == -1)
   {
     if (cont_char == '-')  /* begin continuation */
       m_continuationResponse = m_responseCode;
 
     // display the whole message if no valid response code or
-    // message shorter than 4 chars
-    m_responseText = (m_responseCode >= 100 && PL_strlen(line) > 3) ? line + 4 : line;
+    // message shorter than 4 chars (chars_read)
+    // For now we intentionally leave the ESMTP code in the message text
+    // as we do not handle that code so let it for the user to get some clue.
+    m_responseText = (m_responseCode >= 100 && PL_strlen(line) > 3) ? line + chars_read : line;
   }
   else
   { /* have to continue */
     if (m_continuationResponse == m_responseCode && cont_char == ' ')
       m_continuationResponse = -1;    /* ended */
 
     if (m_responseText.IsEmpty() || m_responseText.Last() != '\n')
       m_responseText += "\n";
 
-    m_responseText += (PL_strlen(line) > 3) ? line + 4 : line;
+    m_responseText += (PL_strlen(line) > 3) ? line + chars_read : line;
   }
 
   if (m_responseCode == 220 && m_responseText.Length() && !m_tlsInitiated &&
      !m_sendDone)
     m_nextStateAfterResponse = SMTP_EXTN_LOGIN_RESPONSE;
 
   if (m_continuationResponse == -1)  /* all done with this response? */
   {
@@ -1716,17 +1731,19 @@ nsresult nsSmtpProtocol::SendMailRespons
 {
   nsresult status = NS_OK;
   nsAutoCString buffer;
   nsresult rv;
 
   if (m_responseCode/10 != 25)
   {
     nsresult errorcode;
-    if (TestFlag(SMTP_EHLO_SIZE_ENABLED))
+    if ((m_responseCodeEnhanced == 570) || (m_responseCodeEnhanced == 571))
+      errorcode = NS_ERROR_SMTP_SEND_NOT_ALLOWED;
+    else if (TestFlag(SMTP_EHLO_SIZE_ENABLED))
       errorcode = (m_responseCode == 452) ? NS_ERROR_SMTP_TEMP_SIZE_EXCEEDED :
                   (m_responseCode == 552) ? NS_ERROR_SMTP_PERM_SIZE_EXCEEDED_2 :
                   NS_ERROR_SENDING_FROM_COMMAND;
     else
       errorcode = NS_ERROR_SENDING_FROM_COMMAND;
 
     rv = nsExplainErrorDetails(m_runningURL, errorcode, m_responseText.get(), nullptr);
     NS_ASSERTION(NS_SUCCEEDED(rv), "failed to explain SMTP error");
@@ -1816,17 +1833,19 @@ nsresult nsSmtpProtocol::SendRecipientRe
 {
   nsresult status = NS_OK;
   nsAutoCString buffer;
   nsresult rv;
 
   if (m_responseCode / 10 != 25)
   {
     nsresult errorcode;
-    if (TestFlag(SMTP_EHLO_SIZE_ENABLED))
+    if ((m_responseCodeEnhanced == 570) || (m_responseCodeEnhanced == 571))
+      errorcode = NS_ERROR_SMTP_SEND_NOT_ALLOWED;
+    else if (TestFlag(SMTP_EHLO_SIZE_ENABLED))
       errorcode = (m_responseCode == 452) ? NS_ERROR_SMTP_TEMP_SIZE_EXCEEDED :
                   (m_responseCode == 552) ? NS_ERROR_SMTP_PERM_SIZE_EXCEEDED_2 :
                   NS_ERROR_SENDING_RCPT_COMMAND;
     else
       errorcode = NS_ERROR_SENDING_RCPT_COMMAND;
 
     rv = nsExplainErrorDetails(m_runningURL, errorcode,
                                m_responseText.get(),
--- a/mailnews/compose/src/nsSmtpProtocol.h
+++ b/mailnews/compose/src/nsSmtpProtocol.h
@@ -119,16 +119,17 @@ private:
     nsresult m_urlErrorState;
     nsCOMPtr<nsIMsgStatusFeedback> m_statusFeedback;
 
     // Generic state information -- What state are we in? What state do we want to go to
     // after the next response? What was the last response code? etc.
     SmtpState m_nextState;
     SmtpState m_nextStateAfterResponse;
     int32_t m_responseCode;    /* code returned from Smtp server */
+    int32_t m_responseCodeEnhanced;    /* ESMTP code returned from SMTP server (RFC1893) */
     int32_t m_previousResponseCode;
     int32_t m_continuationResponse;
     nsCString m_responseText;   /* text returned from Smtp server */
     RefPtr<nsMsgLineStreamBuffer> m_lineStreamBuffer; // used to efficiently extract lines from the incoming data stream
 
     nsTArray<nsCString> m_addresses;
     uint32_t       m_addressesLeft;
     nsCString m_mailAddr;
--- a/suite/locales/en-US/chrome/mailnews/compose/composeMsgs.properties
+++ b/suite/locales/en-US/chrome/mailnews/compose/composeMsgs.properties
@@ -54,24 +54,27 @@ followupToSenderMessage=The author of th
 
 ## LOCALIZATION NOTE (errorAttachingFile): argument %S is the file name/URI of object to be attached
 errorAttachingFile=There was an error attaching %S. Please check that you have access to the file.
 
 ## LOCALIZATION NOTE (incorrectSmtpGreeting): argument %s is the Outgoing server (SMTP) greeting
 incorrectSmtpGreeting=An error occurred while sending mail: The mail server sent an incorrect greeting:  %s.
 
 ## LOCALIZATION NOTE (errorSendingRcptCommand): argument %1$S is the Outgoing server (SMTP) response, argument %2$S is the intended message recipient.
-errorSendingRcptCommand=An error occurred while sending mail. The mail server responded:  \n%1$S.\n Please check the message recipient "%2$S" and try again.
+errorSendingRcptCommand=An error occurred while sending mail. The mail server responded:\n%1$S.\nPlease check the message recipient "%2$S" and try again.
 
 ## LOCALIZATION NOTE (startTlsFailed): argument %S is the Outgoing server (SMTP)
 startTlsFailed=An error occurred while sending mail: Unable to establish a secure link with Outgoing server (SMTP) %S using STARTTLS since it doesn't advertise that feature. Switch off STARTTLS for this server or contact your service provider.
 
 ## LOCALIZATION NOTE (smtpPasswordUndefined): argument %S is the Outgoing server (SMTP) account
 smtpPasswordUndefined=An error occurred while sending mail: Could not get password for %S. The message was not sent.
 
+## LOCALIZATION NOTE (smtpSendNotAllowed): argument %s is the Outgoing server (SMTP) response
+smtpSendNotAllowed=An error occurred while sending mail. The mail server responded:\n%s.\nPlease ensure that you are using the correct identity to send and that the used authentication method is correct. Verify that you are allowed to send via this SMTP server with your current credentials from your current network.
+
 ## LOCALIZATION NOTE (smtpTempSizeExceeded): argument %s is the Outgoing server (SMTP) response
 smtpTempSizeExceeded=The size of the message you are trying to send exceeds a temporary size limit of the server. The message was not sent; try to reduce the message size or wait some time and try again. The server responded:  %s.
 
 ## LOCALIZATION NOTE (smtpPermSizeExceeded1): argument %d is the Outgoing server (SMTP) size limit
 smtpPermSizeExceeded1=The size of the message you are trying to send exceeds the global size limit (%d bytes) of the server. The message was not sent; reduce the message size and try again.
 
 ## LOCALIZATION NOTE (smtpPermSizeExceeded2): argument %s is the server's response
 smtpPermSizeExceeded2=The size of the message you are trying to send exceeds the global size limit of the server. The message was not sent; reduce the message size and try again. The server responded:  %s.