build: use pkg-config for i18n
[exim.git] / src / src / smtp_out.c
index 7f364d9420501e05e9c1eb258b22fe787b0c3d04..2ea29a7e442e6d0e0f386188b35e57e74776b4f8 100644 (file)
@@ -2,9 +2,10 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) The Exim Maintainers 2020 - 2022 */
+/* Copyright (c) The Exim Maintainers 2020 - 2024 */
 /* Copyright (c) University of Cambridge 1995 - 2018 */
 /* See the file NOTICE for conditions of use and distribution. */
+/* SPDX-License-Identifier: GPL-2.0-or-later */
 
 /* A number of functions for driving outgoing SMTP calls. */
 
@@ -260,8 +261,7 @@ int
 smtp_boundsock(smtp_connect_args * sc)
 {
 transport_instance * tb = sc->tblock;
-smtp_transport_options_block * ob =
-  (smtp_transport_options_block *)tb->options_block;
+smtp_transport_options_block * ob = tb->drinst.options_block;
 const uschar * dscp = ob->dscp;
 int sock, dscp_value, dscp_level, dscp_option;
 
@@ -277,6 +277,7 @@ if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, US &on, sizeof(on)))
 /* Set DSCP value, if we can. For now, if we fail to set the value, we don't
 bomb out, just log it and continue in default traffic class. */
 
+GET_OPTION("dscp");
 if (dscp && dscp_lookup(dscp, sc->host_af, &dscp_level, &dscp_option, &dscp_value))
   {
   HDEBUG(D_transport|D_acl|D_v)
@@ -304,7 +305,7 @@ if (sc->interface)
      )
     {
     HDEBUG(D_transport|D_acl|D_v)
-      debug_printf_indent("unable to bind outgoing SMTP call to %s: %s", sc->interface,
+      debug_printf_indent("unable to bind outgoing SMTP call to %s: %s\n", sc->interface,
        strerror(errno));
     close(sock);
     return -1;
@@ -336,8 +337,7 @@ Returns:      connected socket number, or -1 with errno set
 int
 smtp_sock_connect(smtp_connect_args * sc, int timeout, const blob * early_data)
 {
-smtp_transport_options_block * ob =
-  (smtp_transport_options_block *)sc->tblock->options_block;
+smtp_transport_options_block * ob = sc->tblock->drinst.options_block;
 int sock;
 int save_errno = 0;
 const blob * fastopen_blob = NULL;
@@ -363,6 +363,7 @@ if (!save_errno)
   {
 #ifdef TCP_FASTOPEN
   /* See if TCP Fast Open usable.  Default is a traditional 3WHS connect */
+  expand_level++;
   if (verify_check_given_host(CUSS &ob->hosts_try_fastopen, sc->host) == OK)
     {
     if (!early_data)
@@ -378,6 +379,7 @@ if (!save_errno)
       }
 # endif
     }
+  expand_level--;
 #endif
 
   if (ip_connect(sock, sc->host_af, sc->host->address, sc->host->port, timeout, fastopen_blob) < 0)
@@ -410,7 +412,7 @@ if (!save_errno)
 
   /* Both bind() and connect() succeeded, and any early-data */
 
-  HDEBUG(D_transport|D_acl|D_v) debug_printf_indent(" connected\n");
+  HDEBUG(D_transport|D_acl|D_v) debug_printf_indent("connected\n");
   if (getsockname(sock, (struct sockaddr *)(&interface_sock), &size) == 0)
     sending_ip_address = host_ntoa(-1, &interface_sock, NULL, &sending_port);
   else
@@ -494,7 +496,7 @@ HDEBUG(D_transport|D_acl|D_v)
 #ifdef SUPPORT_SOCKS
   if (ob->socks_proxy) s = string_sprintf("%svia proxy ", s);
 #endif
-  debug_printf_indent("Connecting to %s %s%s... ", sc->host->name, callout_address, s);
+  debug_printf_indent("Connecting to %s %s%s...\n", sc->host->name, callout_address, s);
   }
 
 /* Create and connect the socket */
@@ -549,10 +551,10 @@ Returns:     TRUE if OK, FALSE on error, with errno set
 static BOOL
 flush_buffer(smtp_outblock * outblock, int mode)
 {
-int rc;
-int n = outblock->ptr - outblock->buffer;
+int n = outblock->ptr - outblock->buffer, rc;
 BOOL more = mode == SCMD_MORE;
 client_conn_ctx * cctx;
+const uschar * where;
 
 HDEBUG(D_transport|D_acl) debug_printf_indent("cmd buf flush %d bytes%s\n", n,
   more ? " (more expected)" : "");
@@ -565,6 +567,7 @@ if (!(cctx = outblock->cctx))
   }
 
 #ifndef DISABLE_TLS
+where = US"tls_write";
 if (cctx->tls_ctx)             /*XXX have seen a null cctx here, rvfy sending QUIT, hence check above */
   rc = tls_write(cctx->tls_ctx, outblock->buffer, n, more);
 else
@@ -580,6 +583,7 @@ else
     requirement: TFO with data can, in rare cases, replay the data to the
     receiver. */
 
+    where = US"smtp_connect";
     if (  (cctx->sock = smtp_connect(outblock->conn_args, &early_data))
        < 0)
       return FALSE;
@@ -588,6 +592,7 @@ else
     }
   else
     {
+    where = US"send";
     rc = send(cctx->sock, outblock->buffer, n,
 #ifdef MSG_MORE
              more ? MSG_MORE : 0
@@ -602,6 +607,7 @@ else
     This is despite NODELAY being active.
     https://bugzilla.redhat.com/show_bug.cgi?id=1803806 */
 
+    where = US"cork";
     if (!more)
       setsockopt(cctx->sock, IPPROTO_TCP, TCP_CORK, &off, sizeof(off));
 #endif
@@ -610,7 +616,8 @@ else
 
 if (rc <= 0)
   {
-  HDEBUG(D_transport|D_acl) debug_printf_indent("send failed: %s\n", strerror(errno));
+  HDEBUG(D_transport|D_acl) debug_printf_indent("%s (fd %d) failed: %s\n",
+    where, cctx->sock, strerror(errno));
   return FALSE;
   }
 
@@ -621,22 +628,6 @@ return TRUE;
 
 
 
-/* This might be called both due to callout and then from delivery.
-Use memory that will not be released between those phases.
-*/
-static void
-smtp_debug_resp(const uschar * buf)
-{
-#ifndef DISABLE_CLIENT_CMD_LOG
-int old_pool = store_pool;
-store_pool = POOL_PERM;
-client_cmd_log = string_append_listele_n(client_cmd_log, ':', buf,
-  buf[3] == ' ' ? 3 : 4);
-store_pool = old_pool;
-#endif
-}
-
-
 /*************************************************
 *             Write SMTP command                 *
 *************************************************/
@@ -648,7 +639,7 @@ Arguments:
   sx        SMTP connection, contains buffer for pipelining, and socket
   mode       buffer, write-with-more-likely, write
   format     a format, starting with one of
-             of HELO, MAIL FROM, RCPT TO, DATA, ".", or QUIT.
+             of HELO, MAIL FROM, RCPT TO, DATA, BDAT, ".", or QUIT.
             If NULL, flush pipeline buffer only.
   ...        data for the format
 
@@ -679,7 +670,6 @@ if (format)
     log_write(0, LOG_MAIN|LOG_PANIC_DIE, "overlong write_command in outgoing "
       "SMTP");
   va_end(ap);
-  string_from_gstring(&gs);
 
   if (gs.ptr > outblock->buffersize)
     log_write(0, LOG_MAIN|LOG_PANIC_DIE, "overlong write_command in outgoing "
@@ -703,13 +693,13 @@ if (format)
 
   if (outblock->authenticating)
     {
-    uschar *p = big_buffer;
+    uschar * p = big_buffer;
     if (Ustrncmp(big_buffer, "AUTH ", 5) == 0)
       {
       p += 5;
-      while (isspace(*p)) p++;
-      while (!isspace(*p)) p++;
-      while (isspace(*p)) p++;
+      Uskip_whitespace(&p);
+      Uskip_nonwhite(&p);
+      Uskip_whitespace(&p);
       }
     while (*p) *p++ = '*';
     }