64 #include <sys/socket.h>
66 #include <netinet/in.h>
67 #include <arpa/inet.h>
77 #define IPPORT_SMTP 25
119 static SMTP_SESSION *smtp_connect_sock(
int,
struct sockaddr *,
int,
128 const char *myname =
"smtp_connect_unix";
129 struct sockaddr_un sock_un;
130 const char *addr =
STR(iter->
addr);
131 int len = strlen(addr);
139 if (len >= (
int)
sizeof(sock_un.sun_path)) {
140 msg_warn(
"unix-domain name too long: %s", addr);
141 dsb_simple(why,
"4.3.5",
"Server configuration error");
148 memset((
void *) &sock_un, 0,
sizeof(sock_un));
149 sock_un.sun_family = AF_UNIX;
151 sock_un.sun_len = len + 1;
153 memcpy(sock_un.sun_path, addr, len + 1);
158 if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
165 msg_info(
"%s: trying: %s...", myname, addr);
167 return (smtp_connect_sock(sock, (
struct sockaddr *) &sock_un,
168 sizeof(sock_un), iter, why, sess_flags));
176 const char *myname =
"smtp_connect_addr";
177 struct sockaddr_storage ss;
178 struct sockaddr *sa = (
struct sockaddr *) &ss;
182 unsigned port = iter->
port;
193 msg_warn(
"%s: skip address type %s: %m",
195 dsb_simple(why,
"4.4.0",
"network address conversion failed: %m");
202 if ((sock = socket(sa->sa_family, SOCK_STREAM, 0)) < 0)
213 if (sa->sa_family == AF_INET6) {
218 if (sa->sa_family == AF_INET) {
222 bind_var = bind_addr =
"";
225 struct addrinfo *res0;
228 msg_fatal(
"%s: bad %s parameter: %s: %s",
230 if (bind(sock, res0->ai_addr, res0->ai_addrlen) < 0)
231 msg_warn(
"%s: bind %s: %m", myname, bind_addr);
233 msg_info(
"%s: bind %s", myname, bind_addr);
246 struct sockaddr *own_addr = 0;
248 struct sockaddr_storage *s;
250 for (s = addr_list->
addrs; s < addr_list->addrs + addr_list->
used; s++) {
274 msg_info(
"%s: trying: %s[%s] port %d...",
277 return (smtp_connect_sock(sock, sa, salen, iter, why, sess_flags));
282 static SMTP_SESSION *smtp_connect_sock(
int sock,
struct sockaddr *sa,
292 const char *name =
STR(iter->
host);
293 const char *addr =
STR(iter->
addr);
294 unsigned port = iter->
port;
296 start_time = time((time_t *) 0);
308 dsb_simple(why,
"4.4.1",
"connect to %s[%s]:%d: %m",
309 name, addr, ntohs(port));
311 dsb_simple(why,
"4.4.1",
"connect to %s[%s]: %m", name, addr);
320 if (sa->sa_family == AF_INET
322 || sa->sa_family == AF_INET6
335 static char *smtp_parse_destination(
char *destination,
char *def_service,
336 char **hostp,
unsigned *portp)
341 char *protocol =
"tcp";
346 msg_info(
"smtp_parse_destination: %s %s", destination, def_service);
352 if ((err =
host_port(buf, hostp, (
char *) 0, &service, def_service)) != 0)
353 msg_fatal(
"%s in server description: %s", err, destination);
359 if ((port = atoi(service)) >= 65536 || port == 0)
360 msg_fatal(
"bad network port in destination: %s", destination);
361 *portp = htons(port);
363 if ((sp = getservbyname(service, protocol)) == 0)
364 msg_fatal(
"unknown service: %s/%s", service, protocol);
372 static void smtp_cleanup_session(
SMTP_STATE *state)
383 #define POSSIBLE_NOTIFICATION(sender) \
384 (*sender == 0 || strcmp(sender, mail_addr_double_bounce()) == 0)
455 static void smtp_cache_policy(
SMTP_STATE *state,
const char *dest)
473 static void smtp_connect_local(
SMTP_STATE *state,
const char *path)
475 const char *myname =
"smtp_connect_local";
484 msg_warn(
"ignoring \"%s = %s\" setting for non-TCP connections",
494 smtp_cache_policy(state, path);
524 if (!smtp_tls_policy_cache_query(why, state->tls, iter)) {
525 msg_warn(
"TLS policy lookup error for %s/%s: %s",
533 session = smtp_connect_unix(iter, why, state->
misc_flags);
534 if ((state->
session = session) != 0) {
535 session->
state = state;
539 msg_warn(
"%s: opportunistic TLS encryption is not appropriate "
540 "for unix-domain destinations.", myname);
567 msg_panic(
"%s: unix-domain destination not final!", myname);
568 smtp_cleanup_session(state);
574 static void smtp_scrub_addr_list(
HTABLE *cached_addr,
DNS_RR **addr_list)
585 for (addr = *addr_list; addr; addr = next) {
588 msg_warn(
"cannot convert type %s record to printable address",
599 static void smtp_update_addr_list(
DNS_RR **addr_list,
const char *server_addr,
605 struct addrinfo *res0;
632 msg_warn(
"hostaddr_to_sockaddr %s: %s",
635 for (addr = *addr_list; addr; addr = next) {
637 if (
DNS_RR_EQ_SA(addr, (
struct sockaddr *) res0->ai_addr)) {
649 int domain_best_pref)
651 int session_count = 0;
676 smtp_tls_policy_dummy(state->tls);
683 smtp_update_addr_list(addr_list,
STR(iter->
addr), session_count);
688 smtp_cleanup_session(state);
713 for (addr = *addr_list;
SMTP_RCPT_LEFT(state) > 0 && addr; addr = next) {
714 if (addr->
pref != domain_best_pref)
718 msg_warn(
"cannot convert type %s record to printable address",
727 if (!smtp_tls_policy_cache_query(why, state->tls, iter)) {
728 msg_warn(
"TLS policy lookup error for %s/%s: %s",
738 smtp_update_addr_list(addr_list,
STR(iter->
addr), session_count);
745 smtp_cleanup_session(state);
748 return (session_count);
753 static void smtp_connect_inet(
SMTP_STATE *state,
const char *nexthop,
761 int non_fallback_sites;
771 dsb_simple(why,
"4.4.4",
"all network protocols are disabled");
780 argv_add(sites, nexthop, (
char *) 0);
781 if (sites->
argc == 0)
782 msg_panic(
"null destination: \"%s\"", nexthop);
783 non_fallback_sites = sites->
argc;
802 #define IS_FALLBACK_RELAY(cpp, sites, non_fallback_sites) \
803 (*(cpp) && (cpp) >= (sites)->argv + (non_fallback_sites))
818 unsigned domain_best_pref;
828 dest_buf = smtp_parse_destination(dest, def_service, &domain, &port);
830 && ntohs(port) == 465) {
831 msg_info(
"SMTPS wrappermode (TCP port 465) requires setting "
832 "\"%s = yes\", and \"%s = encrypt\" (or stronger)",
846 msg_info(
"connecting to %s port %d", domain, ntohs(port));
879 domain_best_pref = addr_list->
pref;
899 smtp_cache_policy(state, domain);
916 smtp_scrub_addr_list(state->
cache_used, &addr_list);
917 sess_count = addr_count =
918 smtp_reuse_session(state, &addr_list, domain_best_pref);
920 sess_count = addr_count = 0;
949 for (addr = addr_list;
SMTP_RCPT_LEFT(state) > 0 && addr; addr = next) {
954 msg_warn(
"cannot convert type %s record to printable address",
963 if (!smtp_tls_policy_cache_query(why, state->tls, iter)) {
964 msg_warn(
"TLS policy lookup for %s/%s: %s",
971 msg_warn(
"%s requires \"%s = encrypt\" (or stronger)",
983 || addr->
pref == domain_best_pref
986 session = smtp_connect_addr(iter, why, state->
misc_flags);
987 if ((state->
session = session) != 0) {
988 session->
state = state;
990 session->tls_nexthop = domain;
992 if (addr->
pref == domain_best_pref)
1007 if ((retry_plain = session->tls_retry_plain) != 0) {
1036 if ((retry_plain = session->tls_retry_plain) != 0) {
1043 smtp_cleanup_session(state);
1075 "server unavailable or unable to receive mail");
1136 char *destination = request->
nexthop;
1154 if (strncmp(destination,
"unix:", 5) == 0) {
1155 smtp_connect_local(state, destination + 5);
1157 if (strncmp(destination,
"inet:", 5) == 0)
1192 msg_panic(
"smtp_connect: left-over recipients");
const char * dns_strtype(unsigned)
char * var_smtp_bind_addr6
bool var_smtp_tls_wrappermode
SMTP_ITERATOR iterator[1]
HTABLE_INFO * htable_locate(HTABLE *table, const char *key)
#define SMTP_ITER_INIT(iter, _dest, _host, _addr, _port, state)
#define SMTP_HAS_SOFT_DSN(why)
struct SMTP_SESSION * session
void freeaddrinfo(struct addrinfo *ai)
#define THIS_SESSION_IS_CACHED
char * mystrdup(const char *str)
#define SMTP_MISC_FLAG_FIRST_NEXTHOP
ARGV * argv_free(ARGV *argvp)
#define SET_NEXTHOP_STATE(state, nexthop)
bool var_smtp_cache_demand
int smtp_helo(SMTP_STATE *)
NORETURN msg_panic(const char *fmt,...)
#define SMTP_MISC_FLAG_CONN_CACHE_MASK
#define SMTP_MISC_FLAG_CONN_STORE
#define SMTP_HAS_LOOP_DSN(why)
int sane_connect(int sock, struct sockaddr *sa, SOCKADDR_SIZE len)
#define inet_proto_info()
DELIVER_REQUEST * request
struct sockaddr_storage * addrs
void dsb_reset(DSN_BUF *dsb)
#define SOCKADDR_TO_HOSTADDR(sa, salen, host, port, sock)
#define SMTP_ITER_SAVE_DEST(iter)
void argv_add(ARGV *argvp,...)
int smtp_sess_fail(SMTP_STATE *)
#define SMTP_KEY_MASK_SCACHE_ENDP_LABEL
#define VAR_SMTP_FALLBACK
#define POSSIBLE_NOTIFICATION(sender)
const NAME_MASK mail_error_masks[]
int alldig(const char *string)
ARGV * argv_alloc(ssize_t len)
SMTP_SESSION * smtp_session_alloc(VSTREAM *, SMTP_ITERATOR *, time_t, int)
#define SMTP_MISC_FLAG_FINAL_NEXTHOP
#define SMTP_FEATURE_FROM_CACHE
void set_inet_windowsize(int sock, int windowsize)
int hostaddr_to_sockaddr(const char *hostaddr, const char *service, int socktype, struct addrinfo **res)
int var_smtp_mxsess_limit
VSTRING * vstring_strcpy(VSTRING *vp, const char *src)
const char * dns_rr_to_pa(DNS_RR *, MAI_HOSTADDR_STR *)
void smtp_chat_notify(SMTP_SESSION *)
#define string_list_match
#define SMTP_FEATURE_BEST_MX
char buf[MAI_HOSTADDR_STRSIZE]
DNS_RR * dns_rr_remove(DNS_RR *, DNS_RR *)
struct timeval conn_setup_done
#define THIS_SESSION_IS_THROTTLED
int timed_connect(int sock, struct sockaddr *sa, int len, int timeout)
void smtp_save_session(SMTP_STATE *state, int name_key_flags, int endp_key_flags)
#define IS_FALLBACK_RELAY(cpp, sites, non_fallback_sites)
char * var_notify_classes
int dns_rr_to_sa(DNS_RR *, unsigned, struct sockaddr *, SOCKADDR_SIZE *)
int var_smtp_mxaddr_limit
int sock_addr_in_loopback(const struct sockaddr *sa)
#define THIS_SESSION_IS_EXPIRED
STRING_LIST * smtp_cache_dest
#define SOCK_ADDR_PTR(ptr)
void msg_warn(const char *fmt,...)
DNS_RR * smtp_domain_addr(const char *name, DNS_RR **mxrr, int misc_flags, DSN_BUF *why, int *found_myself)
#define SMTP_MISC_FLAG_CONN_LOAD
#define VAR_LMTP_FALLBACK
#define SMTP_MISC_FLAG_FINAL_SERVER
#define name_mask(tag, table, str)
SMTP_SESSION * smtp_reuse_nexthop(SMTP_STATE *state, int name_key_flags)
int deliver_pass_all(const char *class, const char *service, DELIVER_REQUEST *request)
DSN_BUF * dsb_simple(DSN_BUF *dsb, const char *status, const char *format,...)
int smtp_xfer(SMTP_STATE *)
#define THIS_SESSION_IS_FORBIDDEN
NORETURN msg_fatal(const char *fmt,...)
char * var_fallback_relay
#define VAR_NOTIFY_CLASSES
DNS_RR * smtp_host_addr(const char *host, int misc_flags, DSN_BUF *why)
#define SMTP_RCPT_LEFT(state)
int vstream_tweak_tcp(VSTREAM *)
void smtp_rcpt_cleanup(SMTP_STATE *)
INET_ADDR_LIST * own_inet_addr_list(void)
int non_blocking(int, int)
const char * host_port(char *buf, char **host, char *def_host, char **port, char *def_service)
#define SMTP_DNS_DISABLED
#define SOCK_ADDR_LEN(sa)
ARGV * argv_split_append(ARGV *, const char *, const char *)
#define SOCK_ADDR_FAMILY(ptr)
#define DEL_REQ_FLAG_CONN_STORE
#define SMTP_KEY_MASK_SCACHE_DEST_LABEL
int smtp_connect(SMTP_STATE *state)
#define SMTP_MISC_FLAG_LOOP_DETECT
char * var_smtp_bind_addr
#define SMTP_ITER_RESTORE_DEST(iter)
#define SMTP_HAS_DSN(why)
struct timeval deliver_done
void smtp_session_free(SMTP_SESSION *)
#define vstream_ferror(vp)
void dns_rr_free(DNS_RR *)
#define FREE_NEXTHOP_STATE(state)
#define DEL_REQ_FLAG_CONN_LOAD
#define HAVE_NEXTHOP_STATE(state)
#define DNS_RR_EQ_SA(rr, sa)
#define MAIL_CLASS_PRIVATE
int smtp_quit(SMTP_STATE *)
VSTREAM * vstream_fdopen(int fd, int flags)
SMTP_SESSION * smtp_reuse_addr(SMTP_STATE *state, int endp_key_flags)
void msg_info(const char *fmt,...)