Prereq: "3.10.1"
diff -ur --new-file /var/tmp/postfix-3.10.1/src/global/mail_version.h ./src/global/mail_version.h
--- /var/tmp/postfix-3.10.1/src/global/mail_version.h	2025-02-24 10:43:40.000000000 -0500
+++ ./src/global/mail_version.h	2025-04-22 11:14:49.000000000 -0400
@@ -20,8 +20,8 @@
   * Patches change both the patchlevel and the release date. Snapshots have no
   * patchlevel; they change the release date only.
   */
-#define MAIL_RELEASE_DATE	"20250224"
-#define MAIL_VERSION_NUMBER	"3.10.1"
+#define MAIL_RELEASE_DATE	"20250422"
+#define MAIL_VERSION_NUMBER	"3.10.2"
 
 #ifdef SNAPSHOT
 #define MAIL_VERSION_DATE	"-" MAIL_RELEASE_DATE
diff -ur --new-file /var/tmp/postfix-3.10.1/HISTORY ./HISTORY
--- /var/tmp/postfix-3.10.1/HISTORY	2025-02-24 10:58:54.000000000 -0500
+++ ./HISTORY	2025-04-22 08:06:24.000000000 -0400
@@ -29002,3 +29002,30 @@
 	default smtp_tls_dane_insecure_mx_policy setting resulted in
 	unnecessary 'dnssec_probe' warnings, on systems that disable
 	DNSSEC lookups (the default). File: smtp/smtp_addr.c.
+
+20250223
+
+	Documentation: updated link to Dovecot documentation. File:
+	proto/SASL_README.
+
+20250227
+
+	Improved and corrected error messages when converting (host
+	or service) information to (symbolic text, numerical text,
+	or binary) form. File: util/myaddrinfo.c.
+
+20250304
+
+	Bugfix (defect introduced: Postfix 2.3, date 20051222): the
+	Dovecot auth client did not attempt to create a new connection
+	after an I/O error on an existing connection. Reported by
+	Oleksandr Kozmenko. File: xsasl/xsasl_dovecot_server.c.
+
+20250316
+
+	Bugfix (defect introduced: date 19991116): when appending
+	a setting to a main.cf or master.cf file that did not end
+	in a newline character, the "postconf -e" command did not
+	add an extra newline character before appending the new
+	setting, causing information to become garbled. Fix by
+	Michael Tokarev. File: postconf/postconf_edit.c.
diff -ur --new-file /var/tmp/postfix-3.10.1/html/SASL_README.html ./html/SASL_README.html
--- /var/tmp/postfix-3.10.1/html/SASL_README.html	2024-11-21 12:50:17.000000000 -0500
+++ ./html/SASL_README.html	2025-04-21 17:33:26.000000000 -0400
@@ -178,7 +178,7 @@
 <p> Dovecot is a POP/IMAP server that has its own configuration to
 authenticate POP/IMAP clients. When the Postfix SMTP server uses
 Dovecot SASL, it reuses parts of this configuration.  Consult the
-<a href="https://wiki.dovecot.org">Dovecot documentation</a> for how
+<a href="https://doc.dovecot.org">Dovecot documentation</a> for how
 to configure and operate the Dovecot authentication server.  </p>
 
 <h4><a name="server_dovecot_comm">Postfix to Dovecot SASL communication</a></h4>
diff -ur --new-file /var/tmp/postfix-3.10.1/proto/SASL_README.html ./proto/SASL_README.html
--- /var/tmp/postfix-3.10.1/proto/SASL_README.html	2024-11-21 12:49:05.000000000 -0500
+++ ./proto/SASL_README.html	2025-04-21 17:00:34.000000000 -0400
@@ -178,7 +178,7 @@
 <p> Dovecot is a POP/IMAP server that has its own configuration to
 authenticate POP/IMAP clients. When the Postfix SMTP server uses
 Dovecot SASL, it reuses parts of this configuration.  Consult the
-<a href="https://wiki.dovecot.org">Dovecot documentation</a> for how
+<a href="https://doc.dovecot.org">Dovecot documentation</a> for how
 to configure and operate the Dovecot authentication server.  </p>
 
 <h4><a name="server_dovecot_comm">Postfix to Dovecot SASL communication</a></h4>
diff -ur --new-file /var/tmp/postfix-3.10.1/src/postconf/postconf_edit.c ./src/postconf/postconf_edit.c
--- /var/tmp/postfix-3.10.1/src/postconf/postconf_edit.c	2023-05-02 15:26:20.000000000 -0400
+++ ./src/postconf/postconf_edit.c	2025-04-21 16:54:07.000000000 -0400
@@ -113,8 +113,13 @@
 static char *pcf_next_cf_line(VSTRING *buf, VSTREAM *src, VSTREAM *dst, int *lineno)
 {
     char   *cp;
+    int     last_char;
 
-    while (vstring_get(buf, src) != VSTREAM_EOF) {
+    while ((last_char = vstring_get(buf, src)) != VSTREAM_EOF) {
+	if (last_char != '\n') {
+	    VSTRING_ADDCH(buf, '\n');
+	    VSTRING_TERMINATE(buf);
+	}
 	if (lineno)
 	    *lineno += 1;
 	if ((cp = pcf_find_cf_info(buf, dst)) != 0)
diff -ur --new-file /var/tmp/postfix-3.10.1/src/smtpd/smtpd_peer.c ./src/smtpd/smtpd_peer.c
--- /var/tmp/postfix-3.10.1/src/smtpd/smtpd_peer.c	2023-03-14 18:50:33.000000000 -0400
+++ ./src/smtpd/smtpd_peer.c	2025-04-21 16:57:21.000000000 -0400
@@ -217,8 +217,13 @@
 	 */
 	if ((aierr = sockaddr_to_hostaddr(sa, sa_length, &client_addr,
 					  &client_port, 0)) != 0)
-	    msg_fatal("%s: cannot convert client address/port to string: %s",
-		      myname, MAI_STRERROR(aierr));
+	    msg_fatal("%s: cannot convert client sockaddr type %s length %ld "
+		      "to string: %s", myname,
+#ifdef AF_INET6
+		      sa->sa_family == AF_INET6 ? "AF_INET6" :
+#endif
+		      sa->sa_family == AF_INET ? "AF_INET" : "other",
+		      (long) sa_length, MAI_STRERROR(aierr));
 	state->port = mystrdup(client_port.buf);
 
 	/*
@@ -299,9 +304,15 @@
 					  state->dest_sockaddr_len,
 					  &server_addr,
 					  &server_port, 0)) != 0)
-	    msg_fatal("%s: cannot convert server address/port to string: %s",
-		      myname, MAI_STRERROR(aierr));
-	/* TODO: convert IPv4-in-IPv6 to IPv4 form. */
+	    /* TODO: convert IPv4-in-IPv6 to IPv4 form. */
+	    msg_fatal("%s: cannot convert server sockaddr type %s length %ld "
+		    "to string: %s", myname,
+#ifdef AF_INET6
+		   state->dest_sockaddr.ss_family == AF_INET6 ? "AF_INET6" :
+#endif
+		      state->dest_sockaddr.ss_family == AF_INET ? "AF_INET" :
+		      "other", (long) state->dest_sockaddr_len,
+		      MAI_STRERROR(aierr));
 	state->dest_addr = mystrdup(server_addr.buf);
 	state->dest_port = mystrdup(server_port.buf);
 
@@ -409,8 +420,8 @@
 
     if ((aierr = hostaddr_to_sockaddr(state->addr, state->port,
 				      SOCK_STREAM, &res)) != 0)
-	msg_fatal("%s: cannot convert client address/port to string: %s",
-		  myname, MAI_STRERROR(aierr));
+	msg_fatal("%s: cannot convert client address '%s' port '%s' to binary: %s",
+		  myname, state->addr, state->port, MAI_STRERROR(aierr));
     if (res->ai_addrlen > sizeof(state->sockaddr))
 	msg_panic("%s: address length > struct sockaddr_storage", myname);
     memcpy((void *) &(state->sockaddr), res->ai_addr, res->ai_addrlen);
diff -ur --new-file /var/tmp/postfix-3.10.1/src/xsasl/xsasl_dovecot_server.c ./src/xsasl/xsasl_dovecot_server.c
--- /var/tmp/postfix-3.10.1/src/xsasl/xsasl_dovecot_server.c	2024-11-21 12:49:05.000000000 -0500
+++ ./src/xsasl/xsasl_dovecot_server.c	2025-04-21 17:52:38.000000000 -0400
@@ -617,6 +617,7 @@
     }
 
     vstring_strcpy(reply, "Connection lost to authentication server");
+    xsasl_dovecot_server_disconnect(server->impl);
     return XSASL_AUTH_TEMP;
 }
 
@@ -707,6 +708,7 @@
 
 	if (i == 1) {
 	    vstring_strcpy(reply, "Can't connect to authentication server");
+	    xsasl_dovecot_server_disconnect(server->impl);
 	    return XSASL_AUTH_TEMP;
 	}
 
@@ -735,6 +737,7 @@
 		    "CONT\t%u\t%s\n", server->last_request_id, request);
     if (vstream_fflush(server->impl->sasl_stream) == VSTREAM_EOF) {
 	vstring_strcpy(reply, "Connection lost to authentication server");
+	xsasl_dovecot_server_disconnect(server->impl);
 	return XSASL_AUTH_TEMP;
     }
     return xsasl_dovecot_handle_reply(server, reply);