7 /* connect to SMTP/LMTP server and deliver
11 /* int smtp_connect(state)
14 /* This module implements SMTP/LMTP connection management and controls
17 /* smtp_connect() attempts to establish an SMTP/LMTP session with a host
18 /* that represents the destination domain, or with an optional fallback
19 /* relay when {the destination cannot be found, or when all the
20 /* destination servers are unavailable}. It skips over IP addresses
21 /* that fail to complete the SMTP/LMTP handshake and tries to find
22 /* an alternate server when an SMTP/LMTP session fails to deliver.
24 /* This layer also controls what connections are retrieved from
25 /* the connection cache, and what connections are saved to the cache.
27 /* The destination is either a host (or domain) name or a numeric
28 /* address. Symbolic or numeric service port information may be
29 /* appended, separated by a colon (":"). In the case of LMTP,
30 /* destinations may be specified as "unix:pathname", "inet:host"
31 /* or "inet:host:port".
33 /* With SMTP, the Internet domain name service is queried for mail
34 /* exchanger hosts. Quote the domain name with `[' and `]' to
35 /* suppress mail exchanger lookups.
37 /* Numerical address information should always be quoted with `[]'.
39 /* The delivery status is the result value.
41 /* smtp_proto(3) SMTP client protocol
45 /* The Secure Mailer license must be distributed with this software.
48 /* IBM T.J. Watson Research
50 /* Yorktown Heights, NY 10598, USA
52 /* Connection caching in cooperation with:
61 #include <sys/socket.h>
63 #include <netinet/in.h>
64 #include <arpa/inet.h>
74 #define IPPORT_SMTP 25
77 /* Utility library. */
84 #include <inet_addr_list.h>
86 #include <timed_connect.h>
87 #include <stringops.h>
88 #include <host_port.h>
89 #include <sane_connect.h>
90 #include <myaddrinfo.h>
91 #include <sock_addr.h>
95 #include <mail_params.h>
96 #include <own_inet_addr.h>
97 #include <deliver_pass.h>
98 #include <mail_error.h>
105 /* Application-specific. */
108 #include <smtp_addr.h>
109 #include <smtp_reuse.h>
112 * Forward declaration.
114 static SMTP_SESSION
*smtp_connect_sock(int, struct sockaddr
*, int,
115 const char *, const char *,
117 const char *, DSN_BUF
*,
120 /* smtp_connect_unix - connect to UNIX-domain address */
122 static SMTP_SESSION
*smtp_connect_unix(const char *addr
,
126 const char *myname
= "smtp_connect_unix";
127 struct sockaddr_un sock_un
;
128 int len
= strlen(addr
);
131 dsb_reset(why
); /* Paranoia */
136 if (len
>= (int) sizeof(sock_un
.sun_path
)) {
137 msg_warn("unix-domain name too long: %s", addr
);
138 dsb_simple(why
, "4.3.5", "Server configuration error");
145 memset((char *) &sock_un
, 0, sizeof(sock_un
));
146 sock_un
.sun_family
= AF_UNIX
;
148 sock_un
.sun_len
= len
+ 1;
150 memcpy(sock_un
.sun_path
, addr
, len
+ 1);
153 * Create a client socket.
155 if ((sock
= socket(AF_UNIX
, SOCK_STREAM
, 0)) < 0)
156 msg_fatal("%s: socket: %m", myname
);
159 * Connect to the server.
162 msg_info("%s: trying: %s...", myname
, addr
);
164 return (smtp_connect_sock(sock
, (struct sockaddr
*) & sock_un
,
165 sizeof(sock_un
), var_myhostname
, addr
,
166 0, addr
, why
, sess_flags
));
169 /* smtp_connect_addr - connect to explicit address */
171 static SMTP_SESSION
*smtp_connect_addr(const char *destination
, DNS_RR
*addr
,
172 unsigned port
, DSN_BUF
*why
,
175 const char *myname
= "smtp_connect_addr";
176 struct sockaddr_storage ss
; /* remote */
177 struct sockaddr
*sa
= (struct sockaddr
*) & ss
;
178 SOCKADDR_SIZE salen
= sizeof(ss
);
179 MAI_HOSTADDR_STR hostaddr
;
184 dsb_reset(why
); /* Paranoia */
189 if (dns_rr_to_sa(addr
, port
, sa
, &salen
) != 0) {
190 msg_warn("%s: skip address type %s: %m",
191 myname
, dns_strtype(addr
->type
));
192 dsb_simple(why
, "4.4.0", "network address conversion failed: %m");
199 if ((sock
= socket(sa
->sa_family
, SOCK_STREAM
, 0)) < 0)
200 msg_fatal("%s: socket: %m", myname
);
202 if (inet_windowsize
> 0)
203 set_inet_windowsize(sock
, inet_windowsize
);
206 * Allow the sysadmin to specify the source address, for example, as "-o
207 * smtp_bind_address=x.x.x.x" in the master.cf file.
210 if (sa
->sa_family
== AF_INET6
) {
211 bind_addr
= var_smtp_bind_addr6
;
212 bind_var
= VAR_SMTP_BIND_ADDR6
;
215 if (sa
->sa_family
== AF_INET
) {
216 bind_addr
= var_smtp_bind_addr
;
217 bind_var
= VAR_SMTP_BIND_ADDR
;
219 bind_var
= bind_addr
= "";
222 struct addrinfo
*res0
;
224 if ((aierr
= hostaddr_to_sockaddr(bind_addr
, (char *) 0, 0, &res0
)) != 0)
225 msg_fatal("%s: bad %s parameter: %s: %s",
226 myname
, bind_var
, bind_addr
, MAI_STRERROR(aierr
));
227 if (bind(sock
, res0
->ai_addr
, res0
->ai_addrlen
) < 0)
228 msg_warn("%s: bind %s: %m", myname
, bind_addr
);
229 else if (msg_verbose
)
230 msg_info("%s: bind %s", myname
, bind_addr
);
235 * When running as a virtual host, bind to the virtual interface so that
236 * the mail appears to come from the "right" machine address.
238 * XXX The IPv6 patch expands the null host (as client endpoint) and uses
239 * the result as the loopback address list.
243 struct sockaddr
*own_addr
= 0;
244 INET_ADDR_LIST
*addr_list
= own_inet_addr_list();
245 struct sockaddr_storage
*s
;
247 for (s
= addr_list
->addrs
; s
< addr_list
->addrs
+ addr_list
->used
; s
++) {
248 if (SOCK_ADDR_FAMILY(s
) == sa
->sa_family
) {
251 own_addr
= SOCK_ADDR_PTR(s
);
254 if (count
== 1 && !sock_addr_in_loopback(own_addr
)) {
255 if (bind(sock
, own_addr
, SOCK_ADDR_LEN(own_addr
)) < 0) {
256 SOCKADDR_TO_HOSTADDR(own_addr
, SOCK_ADDR_LEN(own_addr
),
257 &hostaddr
, (MAI_SERVPORT_STR
*) 0, 0);
258 msg_warn("%s: bind %s: %m", myname
, hostaddr
.buf
);
259 } else if (msg_verbose
) {
260 SOCKADDR_TO_HOSTADDR(own_addr
, SOCK_ADDR_LEN(own_addr
),
261 &hostaddr
, (MAI_SERVPORT_STR
*) 0, 0);
262 msg_info("%s: bind %s", myname
, hostaddr
.buf
);
268 * Connect to the server.
270 SOCKADDR_TO_HOSTADDR(sa
, salen
, &hostaddr
, (MAI_SERVPORT_STR
*) 0, 0);
272 msg_info("%s: trying: %s[%s] port %d...",
273 myname
, SMTP_HNAME(addr
), hostaddr
.buf
, ntohs(port
));
275 return (smtp_connect_sock(sock
, sa
, salen
, SMTP_HNAME(addr
), hostaddr
.buf
,
276 port
, destination
, why
, sess_flags
));
279 /* smtp_connect_sock - connect a socket over some transport */
281 static SMTP_SESSION
*smtp_connect_sock(int sock
, struct sockaddr
* sa
,
282 int salen
, const char *name
,
285 const char *destination
,
294 start_time
= time((time_t *) 0);
295 if (var_smtp_conn_tmout
> 0) {
296 non_blocking(sock
, NON_BLOCKING
);
297 conn_stat
= timed_connect(sock
, sa
, salen
, var_smtp_conn_tmout
);
299 non_blocking(sock
, BLOCKING
);
302 conn_stat
= sane_connect(sock
, sa
, salen
);
306 dsb_simple(why
, "4.4.1", "connect to %s[%s]:%d: %m",
307 name
, addr
, ntohs(port
));
309 dsb_simple(why
, "4.4.1", "connect to %s[%s]: %m", name
, addr
);
313 stream
= vstream_fdopen(sock
, O_RDWR
);
316 * Avoid poor performance when TCP MSS > VSTREAM_BUFSIZE.
318 if (sa
->sa_family
== AF_INET
320 || sa
->sa_family
== AF_INET6
323 vstream_tweak_tcp(stream
);
326 * Bundle up what we have into a nice SMTP_SESSION object.
328 return (smtp_session_alloc(stream
, destination
, name
, addr
,
329 port
, start_time
, sess_flags
));
332 /* smtp_parse_destination - parse host/port destination */
334 static char *smtp_parse_destination(char *destination
, char *def_service
,
335 char **hostp
, unsigned *portp
)
337 char *buf
= mystrdup(destination
);
340 char *protocol
= "tcp"; /* XXX configurable? */
345 msg_info("smtp_parse_destination: %s %s", destination
, def_service
);
348 * Parse the host/port information. We're working with a copy of the
349 * destination argument so the parsing can be destructive.
351 if ((err
= host_port(buf
, hostp
, (char *) 0, &service
, def_service
)) != 0)
352 msg_fatal("%s in server description: %s", err
, destination
);
355 * Convert service to port number, network byte order.
357 if (alldig(service
)) {
358 if ((port
= atoi(service
)) >= 65536 || port
== 0)
359 msg_fatal("bad network port in destination: %s", destination
);
360 *portp
= htons(port
);
362 if ((sp
= getservbyname(service
, protocol
)) == 0)
363 msg_fatal("unknown service: %s/%s", service
, protocol
);
369 /* smtp_cleanup_session - clean up after using a session */
371 static void smtp_cleanup_session(SMTP_STATE
*state
)
373 DELIVER_REQUEST
*request
= state
->request
;
374 SMTP_SESSION
*session
= state
->session
;
378 * Inform the postmaster of trouble.
380 if (session
->history
!= 0
381 && (session
->error_mask
& name_mask(VAR_NOTIFY_CLASSES
,
383 var_notify_classes
)) != 0)
384 smtp_chat_notify(session
);
387 * When session caching is enabled, cache the first good session for this
388 * delivery request under the next-hop destination, and cache all good
389 * sessions under their server network address (destroying the session in
392 * Caching under the next-hop destination name (rather than the fall-back
393 * destination) allows us to skip over non-responding primary or backup
394 * hosts. In fact, this is the only benefit of caching logical to
395 * physical bindings; caching a session under its own hostname provides
396 * no performance benefit, given the way smtp_connect() works.
398 bad_session
= THIS_SESSION_IS_BAD
; /* smtp_quit() may fail */
399 if (THIS_SESSION_IS_EXPIRED
)
400 smtp_quit(state
); /* also disables caching */
401 if (THIS_SESSION_IS_CACHED
402 /* Redundant tests for safety... */
403 && vstream_ferror(session
->stream
) == 0
404 && vstream_feof(session
->stream
) == 0) {
405 smtp_save_session(state
);
407 smtp_session_free(session
);
412 * If this session was good, reset the logical next-hop state, so that we
413 * won't cache connections to alternate servers under the logical
414 * next-hop destination. Otherwise we could end up skipping over the
415 * available and more preferred servers.
417 if (HAVE_NEXTHOP_STATE(state
) && !bad_session
)
418 FREE_NEXTHOP_STATE(state
);
421 * Clean up the lists with todo and dropped recipients.
423 smtp_rcpt_cleanup(state
);
426 * Reset profiling info.
428 * XXX When one delivery request results in multiple sessions, the set-up
429 * and transmission latencies of the earlier sessions will count as
430 * connection set-up time for the later sessions.
432 * XXX On the other hand, when we first try to connect to one or more dead
433 * hosts before we reach a good host, then all that time must be counted
434 * as connection set-up time for the session with the good host.
436 * XXX So this set-up attribution problem exists only when we actually
437 * engage in a session, spend a lot of time delivering a message, find
438 * that it fails, and then connect to an alternate host.
440 memset((char *) &request
->msg_stats
.conn_setup_done
, 0,
441 sizeof(request
->msg_stats
.conn_setup_done
));
442 memset((char *) &request
->msg_stats
.deliver_done
, 0,
443 sizeof(request
->msg_stats
.deliver_done
));
444 request
->msg_stats
.reuse_count
= 0;
447 static void smtp_cache_policy(SMTP_STATE
*state
, const char *dest
)
449 DELIVER_REQUEST
*request
= state
->request
;
451 state
->misc_flags
&= ~SMTP_MISC_FLAG_CONN_CACHE_MASK
;
454 * XXX Disable connection caching when sender-dependent authentication is
455 * enabled. We must not send someone elses mail over an authenticated
456 * connection, and we must not send mail that requires authentication
457 * over a connection that wasn't authenticated.
459 if (var_smtp_sender_auth
)
462 if (smtp_cache_dest
&& string_list_match(smtp_cache_dest
, dest
)) {
463 state
->misc_flags
|= SMTP_MISC_FLAG_CONN_CACHE_MASK
;
464 } else if (var_smtp_cache_demand
) {
465 if (request
->flags
& DEL_REQ_FLAG_CONN_LOAD
)
466 state
->misc_flags
|= SMTP_MISC_FLAG_CONN_LOAD
;
467 if (request
->flags
& DEL_REQ_FLAG_CONN_STORE
)
468 state
->misc_flags
|= SMTP_MISC_FLAG_CONN_STORE
;
472 /* smtp_connect_local - connect to local server */
474 static void smtp_connect_local(SMTP_STATE
*state
, const char *path
)
476 const char *myname
= "smtp_connect_local";
477 SMTP_SESSION
*session
;
478 DSN_BUF
*why
= state
->why
;
481 * It's too painful to weave this code into the SMTP connection
482 * management routine.
484 * Connection cache management is based on the UNIX-domain pathname, without
485 * the "unix:" prefix.
487 smtp_cache_policy(state
, path
);
490 * XXX We assume that the session->addr member refers to a copy of the
491 * UNIX-domain pathname, so that smtp_save_session() will cache the
492 * connection using the pathname as the physical endpoint name.
497 * Opportunistic TLS for unix domain sockets does not make much sense,
498 * since the channel is private, mere encryption without authentication
499 * is just wasted cycles and opportunity for breakage. Since we are not
500 * willing to retry after TLS handshake failures here, we downgrade "may"
501 * no "none". Nothing is lost, and much waste is avoided.
503 * We don't know who is authenticating whom, so if a client cert is
504 * available, "encrypt" may be a sensible policy. Otherwise, we also
505 * downgrade "encrypt" to "none", this time just to avoid waste.
507 if ((state
->misc_flags
& SMTP_MISC_FLAG_CONN_LOAD
) == 0
508 || (session
= smtp_reuse_addr(state
, path
, NO_PORT
)) == 0)
509 session
= smtp_connect_unix(path
, why
, state
->misc_flags
);
510 if ((state
->session
= session
) != 0) {
511 session
->state
= state
;
513 session
->tls_nexthop
= var_myhostname
; /* for TLS_LEV_SECURE */
514 if (session
->tls_level
== TLS_LEV_MAY
) {
515 msg_warn("%s: opportunistic TLS encryption is not appropriate "
516 "for unix-domain destinations.", myname
);
517 session
->tls_level
= TLS_LEV_NONE
;
520 /* All delivery errors bounce or defer. */
521 state
->misc_flags
|= SMTP_MISC_FLAG_FINAL_SERVER
;
524 * When a TLS handshake fails, the stream is marked "dead" to avoid
525 * further I/O over a broken channel.
527 if ((session
->features
& SMTP_FEATURE_FROM_CACHE
) == 0
528 && smtp_helo(state
) != 0) {
529 if (!THIS_SESSION_IS_DEAD
530 && vstream_ferror(session
->stream
) == 0
531 && vstream_feof(session
->stream
) == 0)
538 * With opportunistic TLS disabled we don't expect to be asked to
539 * retry connections without TLS, and so we expect the final server
542 if ((state
->misc_flags
& SMTP_MISC_FLAG_FINAL_SERVER
) == 0)
543 msg_panic("%s: unix-domain destination not final!", myname
);
544 smtp_cleanup_session(state
);
548 /* smtp_scrub_address_list - delete all cached addresses from list */
550 static void smtp_scrub_addr_list(HTABLE
*cached_addr
, DNS_RR
**addr_list
)
552 MAI_HOSTADDR_STR hostaddr
;
557 * XXX Extend the DNS_RR structure with fields for the printable address
558 * and/or binary sockaddr representations, so that we can avoid repeated
559 * binary->string transformations for the same address.
561 for (addr
= *addr_list
; addr
; addr
= next
) {
563 if (dns_rr_to_pa(addr
, &hostaddr
) == 0) {
564 msg_warn("cannot convert type %s resource record to socket address",
565 dns_strtype(addr
->type
));
568 if (htable_locate(cached_addr
, hostaddr
.buf
))
569 *addr_list
= dns_rr_remove(*addr_list
, addr
);
573 /* smtp_update_addr_list - common address list update */
575 static void smtp_update_addr_list(DNS_RR
**addr_list
, const char *server_addr
,
581 struct addrinfo
*res0
;
587 * Truncate the address list if we are not going to use it anyway.
589 if (session_count
== var_smtp_mxsess_limit
590 || session_count
== var_smtp_mxaddr_limit
) {
591 dns_rr_free(*addr_list
);
597 * Convert server address to internal form, and look it up in the address
600 * XXX smtp_reuse_session() breaks if we remove two or more adjacent list
601 * elements but do not truncate the list to zero length.
603 * XXX Extend the SMTP_SESSION structure with sockaddr information so that
604 * we can avoid repeated string->binary transformations for the same
607 if ((aierr
= hostaddr_to_sockaddr(server_addr
, (char *) 0, 0, &res0
)) != 0) {
608 msg_warn("hostaddr_to_sockaddr %s: %s",
609 server_addr
, MAI_STRERROR(aierr
));
611 for (addr
= *addr_list
; addr
; addr
= next
) {
613 if (DNS_RR_EQ_SA(addr
, (struct sockaddr
*) res0
->ai_addr
)) {
614 *addr_list
= dns_rr_remove(*addr_list
, addr
);
622 /* smtp_reuse_session - try to use existing connection, return session count */
624 static int smtp_reuse_session(SMTP_STATE
*state
, int lookup_mx
,
625 const char *domain
, unsigned port
,
626 DNS_RR
**addr_list
, int domain_best_pref
)
628 int session_count
= 0;
631 MAI_HOSTADDR_STR hostaddr
;
632 SMTP_SESSION
*session
;
635 * First, search the cache by logical destination. We truncate the server
636 * address list when all the sessions for this destination are used up,
637 * to reduce the number of variables that need to be checked later.
639 * Note: lookup by logical destination restores the "best MX" bit.
641 if (*addr_list
&& SMTP_RCPT_LEFT(state
) > 0
642 && (session
= smtp_reuse_domain(state
, lookup_mx
, domain
, port
)) != 0) {
644 smtp_update_addr_list(addr_list
, session
->addr
, session_count
);
645 if ((state
->misc_flags
& SMTP_MISC_FLAG_FINAL_NEXTHOP
)
647 state
->misc_flags
|= SMTP_MISC_FLAG_FINAL_SERVER
;
649 smtp_cleanup_session(state
);
653 * Second, search the cache by primary MX address. Again, we use address
654 * list truncation so that we have to check fewer variables later.
656 * XXX This loop is safe because smtp_update_addr_list() either truncates
657 * the list to zero length, or removes at most one list element.
659 for (addr
= *addr_list
; SMTP_RCPT_LEFT(state
) > 0 && addr
; addr
= next
) {
660 if (addr
->pref
!= domain_best_pref
)
663 if (dns_rr_to_pa(addr
, &hostaddr
) != 0
664 && (session
= smtp_reuse_addr(state
, hostaddr
.buf
, port
)) != 0) {
665 session
->features
|= SMTP_FEATURE_BEST_MX
;
667 smtp_update_addr_list(addr_list
, session
->addr
, session_count
);
670 if ((state
->misc_flags
& SMTP_MISC_FLAG_FINAL_NEXTHOP
)
672 state
->misc_flags
|= SMTP_MISC_FLAG_FINAL_SERVER
;
674 smtp_cleanup_session(state
);
677 return (session_count
);
680 /* smtp_connect_remote - establish remote connection */
682 static void smtp_connect_remote(SMTP_STATE
*state
, const char *nexthop
,
685 DELIVER_REQUEST
*request
= state
->request
;
689 int non_fallback_sites
;
691 DSN_BUF
*why
= state
->why
;
694 * First try to deliver to the indicated destination, then try to deliver
695 * to the optional fall-back relays.
697 * Future proofing: do a null destination sanity check in case we allow the
698 * primary destination to be a list (it could be just separators).
700 sites
= argv_alloc(1);
701 argv_add(sites
, nexthop
, (char *) 0);
702 if (sites
->argc
== 0)
703 msg_panic("null destination: \"%s\"", nexthop
);
704 non_fallback_sites
= sites
->argc
;
705 if ((state
->misc_flags
& SMTP_MISC_FLAG_USE_LMTP
) == 0)
706 argv_split_append(sites
, var_fallback_relay
, ", \t\r\n");
709 * Don't give up after a hard host lookup error until we have tried the
710 * fallback relay servers.
712 * Don't bounce mail after a host lookup problem with a relayhost or with a
715 * Don't give up after a qualifying soft error until we have tried all
716 * qualifying backup mail servers.
718 * All this means that error handling and error reporting depends on whether
719 * the error qualifies for trying to deliver to a backup mail server, or
720 * whether we're looking up a relayhost or fallback relay. The challenge
721 * then is to build this into the pre-existing SMTP client without
722 * getting lost in the complexity.
724 #define IS_FALLBACK_RELAY(cpp, sites, non_fallback_sites) \
725 (*(cpp) && (cpp) >= (sites)->argv + (non_fallback_sites))
727 for (cpp
= sites
->argv
, (state
->misc_flags
|= SMTP_MISC_FLAG_FIRST_NEXTHOP
);
728 SMTP_RCPT_LEFT(state
) > 0 && (dest
= *cpp
) != 0;
729 cpp
++, (state
->misc_flags
&= ~SMTP_MISC_FLAG_FIRST_NEXTHOP
)) {
738 SMTP_SESSION
*session
;
740 unsigned domain_best_pref
;
741 MAI_HOSTADDR_STR hostaddr
;
744 state
->misc_flags
|= SMTP_MISC_FLAG_FINAL_NEXTHOP
;
747 * Parse the destination. Default is to use the SMTP port. Look up
748 * the address instead of the mail exchanger when a quoted host is
749 * specified, or when DNS lookups are disabled.
751 dest_buf
= smtp_parse_destination(dest
, def_service
, &domain
, &port
);
754 * Resolve an SMTP server. Skip mail exchanger lookups when a quoted
755 * host is specified, or when DNS lookups are disabled.
758 msg_info("connecting to %s port %d", domain
, ntohs(port
));
759 if ((state
->misc_flags
& SMTP_MISC_FLAG_USE_LMTP
) == 0) {
760 if (ntohs(port
) == IPPORT_SMTP
)
761 state
->misc_flags
|= SMTP_MISC_FLAG_LOOP_DETECT
;
763 state
->misc_flags
&= ~SMTP_MISC_FLAG_LOOP_DETECT
;
764 lookup_mx
= (var_disable_dns
== 0 && *dest
!= '[');
768 addr_list
= smtp_host_addr(domain
, state
->misc_flags
, why
);
769 /* XXX We could be an MX host for this destination... */
773 addr_list
= smtp_domain_addr(domain
, state
->misc_flags
,
775 /* If we're MX host, don't connect to non-MX backups. */
777 state
->misc_flags
|= SMTP_MISC_FLAG_FINAL_NEXTHOP
;
781 * Don't try fall-back hosts if mail loops to myself. That would just
782 * make the problem worse.
784 if (addr_list
== 0 && SMTP_HAS_LOOP_DSN(why
))
785 state
->misc_flags
|= SMTP_MISC_FLAG_FINAL_NEXTHOP
;
788 * No early loop exit or we have a memory leak with dest_buf.
791 domain_best_pref
= addr_list
->pref
;
794 * When session caching is enabled, store the first good session for
795 * this delivery request under the next-hop destination name. All
796 * good sessions will be stored under their specific server IP
799 * XXX Replace sites->argv by (lookup_mx, domain, port) triples so we
800 * don't have to make clumsy ad-hoc copies and keep track of who
801 * free()s the memory.
803 * XXX smtp_session_cache_destinations specifies domain names without
804 * :port, because : is already used for maptype:mapname. Because of
805 * this limitation we use the bare domain without the optional [] or
806 * non-default TCP port.
808 * Opportunistic (a.k.a. on-demand) session caching on request by the
809 * queue manager. This is turned temporarily when a destination has a
810 * high volume of mail in the active queue.
812 * XXX Disable connection caching when sender-dependent authentication
813 * is enabled. We must not send someone elses mail over an
814 * authenticated connection, and we must not send mail that requires
815 * authentication over a connection that wasn't authenticated.
817 if (addr_list
&& (state
->misc_flags
& SMTP_MISC_FLAG_FIRST_NEXTHOP
)) {
818 smtp_cache_policy(state
, domain
);
819 if (state
->misc_flags
& SMTP_MISC_FLAG_CONN_STORE
)
820 SET_NEXTHOP_STATE(state
, lookup_mx
, domain
, port
);
824 * Delete visited cached hosts from the address list.
826 * Optionally search the connection cache by domain name or by primary
827 * MX address before we try to create new connections.
829 * Enforce the MX session and MX address counts per next-hop or
830 * fall-back destination. smtp_reuse_session() will truncate the
831 * address list when either limit is reached.
833 if (addr_list
&& (state
->misc_flags
& SMTP_MISC_FLAG_CONN_LOAD
)) {
834 if (state
->cache_used
->used
> 0)
835 smtp_scrub_addr_list(state
->cache_used
, &addr_list
);
836 sess_count
= addr_count
=
837 smtp_reuse_session(state
, lookup_mx
, domain
, port
,
838 &addr_list
, domain_best_pref
);
840 sess_count
= addr_count
= 0;
843 * Connect to an SMTP server: create primary MX connections, and
844 * reuse or create backup MX connections.
846 * At the start of an SMTP session, all recipients are unmarked. In the
847 * course of an SMTP session, recipients are marked as KEEP (deliver
848 * to alternate mail server) or DROP (remove from recipient list). At
849 * the end of an SMTP session, weed out the recipient list. Unmark
850 * any left-over recipients and try to deliver them to a backup mail
853 * Cache the first good session under the next-hop destination name.
854 * Cache all good sessions under their physical endpoint.
856 * Don't query the session cache for primary MX hosts. We already did
857 * that in smtp_reuse_session(), and if any were found in the cache,
858 * they were already deleted from the address list.
860 for (addr
= addr_list
; SMTP_RCPT_LEFT(state
) > 0 && addr
; addr
= next
) {
862 if (++addr_count
== var_smtp_mxaddr_limit
)
864 if ((state
->misc_flags
& SMTP_MISC_FLAG_CONN_LOAD
) == 0
865 || addr
->pref
== domain_best_pref
866 || dns_rr_to_pa(addr
, &hostaddr
) == 0
867 || !(session
= smtp_reuse_addr(state
, hostaddr
.buf
, port
)))
868 session
= smtp_connect_addr(dest
, addr
, port
, why
,
870 if ((state
->session
= session
) != 0) {
871 session
->state
= state
;
872 if (addr
->pref
== domain_best_pref
)
873 session
->features
|= SMTP_FEATURE_BEST_MX
;
874 /* Don't count handshake errors towards the session limit. */
875 if ((state
->misc_flags
& SMTP_MISC_FLAG_FINAL_NEXTHOP
)
877 state
->misc_flags
|= SMTP_MISC_FLAG_FINAL_SERVER
;
879 /* Disable TLS when retrying after a handshake failure */
881 if (session
->tls_level
>= TLS_LEV_ENCRYPT
)
882 msg_panic("Plain-text retry wrong for mandatory TLS");
883 session
->tls_level
= TLS_LEV_NONE
;
886 session
->tls_nexthop
= domain
; /* for TLS_LEV_SECURE */
888 if ((session
->features
& SMTP_FEATURE_FROM_CACHE
) == 0
889 && smtp_helo(state
) != 0) {
893 * When an opportunistic TLS handshake fails, try the
894 * same address again, with TLS disabled. See also the
895 * RETRY_AS_PLAINTEXT macro.
897 if ((retry_plain
= session
->tls_retry_plain
) != 0) {
904 * When a TLS handshake fails, the stream is marked
905 * "dead" to avoid further I/O over a broken channel.
907 if (!THIS_SESSION_IS_DEAD
908 && vstream_ferror(session
->stream
) == 0
909 && vstream_feof(session
->stream
) == 0)
912 /* Do count delivery errors towards the session limit. */
913 if (++sess_count
== var_smtp_mxsess_limit
)
915 if ((state
->misc_flags
& SMTP_MISC_FLAG_FINAL_NEXTHOP
)
917 state
->misc_flags
|= SMTP_MISC_FLAG_FINAL_SERVER
;
920 smtp_cleanup_session(state
);
922 /* The reason already includes the IP address and TCP port. */
923 msg_info("%s", STR(why
->reason
));
925 /* Insert: test if we must skip the remaining MX hosts. */
927 dns_rr_free(addr_list
);
929 if (state
->misc_flags
& SMTP_MISC_FLAG_FINAL_NEXTHOP
)
934 * We still need to deliver, bounce or defer some left-over recipients:
935 * either mail loops or some backup mail server was unavailable.
937 if (SMTP_RCPT_LEFT(state
) > 0) {
940 * In case of a "no error" indication we make up an excuse: we did
941 * find the host address, but we did not attempt to connect to it.
942 * This can happen when the fall-back relay was already tried via a
943 * cached connection, so that the address list scrubber left behind
946 if (!SMTP_HAS_DSN(why
)) {
947 dsb_simple(why
, "4.3.0",
948 "server unavailable or unable to receive mail");
952 * Pay attention to what could be configuration problems, and pretend
953 * that these are recoverable rather than bouncing the mail.
955 else if (!SMTP_HAS_SOFT_DSN(why
)
956 && (state
->misc_flags
& SMTP_MISC_FLAG_USE_LMTP
) == 0) {
959 * The fall-back destination did not resolve as expected, or it
960 * is refusing to talk to us, or mail for it loops back to us.
962 if (IS_FALLBACK_RELAY(cpp
, sites
, non_fallback_sites
)) {
963 msg_warn("%s configuration problem", VAR_SMTP_FALLBACK
);
964 vstring_strcpy(why
->status
, "4.3.5");
965 /* XXX Keep the diagnostic code and MTA. */
969 * The next-hop relayhost did not resolve as expected, or it is
970 * refusing to talk to us, or mail for it loops back to us.
972 else if (strcmp(sites
->argv
[0], var_relayhost
) == 0) {
973 msg_warn("%s configuration problem", VAR_RELAYHOST
);
974 vstring_strcpy(why
->status
, "4.3.5");
975 /* XXX Keep the diagnostic code and MTA. */
979 * Mail for the next-hop destination loops back to myself. Pass
980 * the mail to the best_mx_transport or bounce it.
982 else if (SMTP_HAS_LOOP_DSN(why
) && *var_bestmx_transp
) {
983 dsb_reset(why
); /* XXX */
984 state
->status
= deliver_pass_all(MAIL_CLASS_PRIVATE
,
987 SMTP_RCPT_LEFT(state
) = 0; /* XXX */
995 if (HAVE_NEXTHOP_STATE(state
))
996 FREE_NEXTHOP_STATE(state
);
1000 /* smtp_connect - establish SMTP connection */
1002 int smtp_connect(SMTP_STATE
*state
)
1004 DELIVER_REQUEST
*request
= state
->request
;
1005 char *destination
= request
->nexthop
;
1008 * All deliveries proceed along the same lines, whether they are over TCP
1009 * or UNIX-domain sockets, and whether they use SMTP or LMTP: get a
1010 * connection from the cache or create a new connection; deliver mail;
1011 * update the connection cache or disconnect.
1013 * The major differences appear at a higher level: the expansion from
1014 * destination to address list, and whether to stop before we reach the
1017 #define DEF_LMTP_SERVICE var_lmtp_tcp_port
1018 #define DEF_SMTP_SERVICE "smtp"
1021 * With LMTP we have direct-to-host delivery only. The destination may
1022 * have multiple IP addresses.
1024 if (state
->misc_flags
& SMTP_MISC_FLAG_USE_LMTP
) {
1025 if (strncmp(destination
, "unix:", 5) == 0) {
1026 smtp_connect_local(state
, destination
+ 5);
1028 if (strncmp(destination
, "inet:", 5) == 0)
1030 smtp_connect_remote(state
, destination
, DEF_LMTP_SERVICE
);
1035 * With SMTP we can have indirection via MX host lookup, as well as an
1036 * optional fall-back relayhost that we must avoid when we are MX host.
1038 * XXX We don't add support for "unix:" or "inet:" prefixes in SMTP
1039 * destinations, because that would break compatibility with existing
1040 * Postfix configurations that have a host with such a name.
1043 smtp_connect_remote(state
, destination
, DEF_SMTP_SERVICE
);
1047 * We still need to bounce or defer some left-over recipients: either
1048 * (SMTP) mail loops or some server was unavailable.
1050 * We could avoid this (and the "final server" complexity) by keeping one
1051 * DSN structure per recipient in memory, by updating those in-memory
1052 * structures with each delivery attempt, and by always flushing all
1053 * deferred recipients at the end. We'd probably still want to bounce
1054 * recipients immediately, so we'd end up with another chunk of code for
1055 * defer logging only.
1057 if (SMTP_RCPT_LEFT(state
) > 0) {
1058 state
->misc_flags
|= SMTP_MISC_FLAG_FINAL_SERVER
; /* XXX */
1059 smtp_sess_fail(state
);
1062 * Sanity check. Don't silently lose recipients.
1064 smtp_rcpt_cleanup(state
);
1065 if (SMTP_RCPT_LEFT(state
) > 0)
1066 msg_panic("smtp_connect: left-over recipients");
1068 return (state
->status
);