1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365
|
/*++
/* NAME
/* smtp 8
/* SUMMARY
/* Postfix remote delivery via SMTP
/* SYNOPSIS
/* \fBsmtp\fR [generic Postfix daemon options]
/* DESCRIPTION
/* The SMTP client processes message delivery requests from
/* the queue manager. Each request specifies a queue file, a sender
/* address, a domain or host to deliver to, and recipient information.
/* This program expects to be run from the \fBmaster\fR(8) process
/* manager.
/*
/* The SMTP client updates the queue file and marks recipients
/* as finished, or it informs the queue manager that delivery should
/* be tried again at a later time. Delivery problem reports are sent
/* to the \fBbounce\fR(8) or \fBdefer\fR(8) daemon as appropriate.
/*
/* The SMTP client looks up a list of mail exchanger addresses for
/* the destination host, sorts the list by preference, and connects
/* to each listed address until it finds a server that responds.
/*
/* Once the SMTP client has received the server greeting banner, no
/* error will cause it to proceed to the next address on the mail
/* exchanger list. Instead, the message is either bounced, or its
/* delivery is deferred until later.
/* SECURITY
/* .ad
/* .fi
/* The SMTP client is moderately security-sensitive. It talks to SMTP
/* servers and to DNS servers on the network. The SMTP client can be
/* run chrooted at fixed low privilege.
/* STANDARDS
/* RFC 821 (SMTP protocol)
/* RFC 1651 (SMTP service extensions)
/* RFC 1870 (Message Size Declaration)
/* RFC 2197 (Pipelining)
/* DIAGNOSTICS
/* Problems and transactions are logged to \fBsyslogd\fR(8).
/* Corrupted message files are marked so that the queue manager can
/* move them to the \fBcorrupt\fR queue for further inspection.
/*
/* Depending on the setting of the \fBnotify_classes\fR parameter,
/* the postmaster is notified of bounces, protocol problems, and of
/* other trouble.
/* BUGS
/* CONFIGURATION PARAMETERS
/* .ad
/* .fi
/* The following \fBmain.cf\fR parameters are especially relevant to
/* this program. See the Postfix \fBmain.cf\fR file for syntax details
/* and for default values. Use the \fBpostfix reload\fR command after
/* a configuration change.
/* .SH Miscellaneous
/* .ad
/* .fi
/* .IP \fBbest_mx_transport\fR
/* Name of the delivery transport to use when the local machine
/* is the most-preferred mail exchanger (by default, a mailer
/* loop is reported, and the message is bounced).
/* .IP \fBdebug_peer_level\fR
/* Verbose logging level increment for hosts that match a
/* pattern in the \fBdebug_peer_list\fR parameter.
/* .IP \fBdebug_peer_list\fR
/* List of domain or network patterns. When a remote host matches
/* a pattern, increase the verbose logging level by the amount
/* specified in the \fBdebug_peer_level\fR parameter.
/* .IP \fBdisable_dns_lookups\fR
/* Disable DNS lookups. This means that mail must be forwarded
/* via a smart relay host.
/* .IP \fBerror_notice_recipient\fR
/* Recipient of protocol/policy/resource/software error notices.
/* .IP \fBfallback_relay\fR
/* Hosts to hand off mail to if a message destination is not found
/* or if a destination is unreachable.
/* .IP \fBignore_mx_lookup_error\fR
/* When a name server fails to respond to an MX query, search for an
/* A record instead of assuming that the name server will recover.
/* .IP \fBinet_interfaces\fR
/* The network interface addresses that this mail system receives
/* mail on. When any of those addresses appears in the list of mail
/* exchangers for a remote destination, the list is truncated to
/* avoid mail delivery loops.
/* .IP \fBnotify_classes\fR
/* When this parameter includes the \fBprotocol\fR class, send mail to the
/* postmaster with transcripts of SMTP sessions with protocol errors.
/* .IP \fBsmtp_skip_4xx_greeting\fR
/* Skip servers that greet us with a 4xx status code.
/* .IP \fBsmtp_skip_quit_response\fR
/* Do not wait for the server response after sending QUIT.
/* .SH "Resource controls"
/* .ad
/* .fi
/* .IP \fBsmtp_destination_concurrency_limit\fR
/* Limit the number of parallel deliveries to the same destination.
/* The default limit is taken from the
/* \fBdefault_destination_concurrency_limit\fR parameter.
/* .IP \fBsmtp_destination_recipient_limit\fR
/* Limit the number of recipients per message delivery.
/* The default limit is taken from the
/* \fBdefault_destination_recipient_limit\fR parameter.
/* .SH "Timeout controls"
/* .ad
/* .fi
/* .IP \fBsmtp_connect_timeout\fR
/* Timeout in seconds for completing a TCP connection. When no
/* connection can be made within the deadline, the SMTP client
/* tries the next address on the mail exchanger list.
/* .IP \fBsmtp_helo_timeout\fR
/* Timeout in seconds for receiving the SMTP greeting banner.
/* When the server drops the connection without sending a
/* greeting banner, or when it sends no greeting banner within the
/* deadline, the SMTP client tries the next address on the mail
/* exchanger list.
/* .IP \fBsmtp_helo_timeout\fR
/* Timeout in seconds for sending the \fBHELO\fR command, and for
/* receiving the server response.
/* .IP \fBsmtp_mail_timeout\fR
/* Timeout in seconds for sending the \fBMAIL FROM\fR command, and for
/* receiving the server response.
/* .IP \fBsmtp_rcpt_timeout\fR
/* Timeout in seconds for sending the \fBRCPT TO\fR command, and for
/* receiving the server response.
/* .IP \fBsmtp_data_init_timeout\fR
/* Timeout in seconds for sending the \fBDATA\fR command, and for
/* receiving the server response.
/* .IP \fBsmtp_data_xfer_timeout\fR
/* Timeout in seconds for sending the message content.
/* .IP \fBsmtp_data_done_timeout\fR
/* Timeout in seconds for sending the "\fB.\fR" command, and for
/* receiving the server response. When no response is received, a
/* warning is logged that the mail may be delivered multiple times.
/* .IP \fBsmtp_quit_timeout\fR
/* Timeout in seconds for sending the \fBQUIT\fR command, and for
/* receiving the server response.
/* SEE ALSO
/* bounce(8) non-delivery status reports
/* master(8) process manager
/* qmgr(8) queue manager
/* syslogd(8) system logging
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/* Wietse Venema
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*--*/
/* System library. */
#include <sys_defs.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <dict.h>
/* Utility library. */
#include <msg.h>
#include <mymalloc.h>
#include <name_mask.h>
/* Global library. */
#include <deliver_request.h>
#include <mail_params.h>
#include <mail_conf.h>
#include <debug_peer.h>
#include <mail_error.h>
#include <deliver_pass.h>
/* Single server skeleton. */
#include <mail_server.h>
/* Application-specific. */
#include "smtp.h"
/*
* Tunable parameters. These have compiled-in defaults that can be overruled
* by settings in the global Postfix configuration file.
*/
int var_smtp_conn_tmout;
int var_smtp_helo_tmout;
int var_smtp_mail_tmout;
int var_smtp_rcpt_tmout;
int var_smtp_data0_tmout;
int var_smtp_data1_tmout;
int var_smtp_data2_tmout;
int var_smtp_quit_tmout;
char *var_inet_interfaces;
char *var_debug_peer_list;
int var_debug_peer_level;
char *var_notify_classes;
int var_smtp_skip_4xx_greeting;
int var_ign_mx_lookup_err;
int var_skip_quit_resp;
char *var_fallback_relay;
char *var_bestmx_transp;
char *var_error_rcpt;
/*
* Global variables. smtp_errno is set by the address lookup routines and by
* the connection management routines.
*/
int smtp_errno;
/* deliver_message - deliver message with extreme prejudice */
static int deliver_message(DELIVER_REQUEST *request)
{
VSTRING *why;
SMTP_STATE *state;
int result;
if (msg_verbose)
msg_info("deliver_message: from %s", request->sender);
/*
* Sanity checks. The smtp server is unprivileged and chrooted, so we can
* afford to distribute the data censoring code, instead of having it all
* in one place.
*/
if (request->nexthop[0] == 0)
msg_fatal("empty nexthop hostname");
if (request->rcpt_list.len <= 0)
msg_fatal("recipient count: %d", request->rcpt_list.len);
/*
* Initialize. Bundle all information about the delivery request, so that
* we can produce understandable diagnostics when something goes wrong
* many levels below. The alternative would be to make everything global.
*/
why = vstring_alloc(100);
state = smtp_state_alloc();
state->request = request;
state->src = request->fp;
/*
* Establish an SMTP session and deliver this message to all requested
* recipients. At the end, notify the postmaster of any protocol errors.
* Optionally deliver mail locally when this machine is the best mail
* exchanger.
*/
if ((state->session = smtp_connect(request->nexthop, why)) == 0) {
if (smtp_errno == SMTP_OK) {
if (*var_bestmx_transp == 0)
msg_panic("smtp_errno botch");
state->status = deliver_pass_all(MAIL_CLASS_PRIVATE,
var_bestmx_transp,
request);
} else
smtp_site_fail(state, smtp_errno == SMTP_RETRY ? 450 : 550,
"%s", vstring_str(why));
} else {
debug_peer_check(state->session->host, state->session->addr);
if (smtp_helo(state) == 0)
smtp_xfer(state);
if (state->history != 0
&& (state->error_mask & name_mask(mail_error_masks, var_notify_classes)))
smtp_chat_notify(state);
smtp_session_free(state->session);
debug_peer_restore();
}
/*
* Clean up.
*/
vstring_free(why);
smtp_chat_reset(state);
result = state->status;
smtp_state_free(state);
return (result);
}
/* smtp_service - perform service for client */
static void smtp_service(VSTREAM *client_stream, char *unused_service, char **argv)
{
DELIVER_REQUEST *request;
int status;
/*
* Sanity check. This service takes no command-line arguments.
*/
if (argv[0])
msg_fatal("unexpected command-line argument: %s", argv[0]);
/*
* This routine runs whenever a client connects to the UNIX-domain socket
* dedicated to remote SMTP delivery service. What we see below is a
* little protocol to (1) tell the queue manager that we are ready, (2)
* read a request from the queue manager, and (3) report the completion
* status of that request. All connection-management stuff is handled by
* the common code in single_server.c.
*/
if ((request = deliver_request_read(client_stream)) != 0) {
status = deliver_message(request);
deliver_request_done(client_stream, request, status);
}
}
/* pre_init - pre-jail initialization */
static void pre_init(char *unused_name, char **unused_argv)
{
debug_peer_init();
}
/* pre_accept - see if tables have changed */
static void pre_accept(char *unused_name, char **unused_argv)
{
if (dict_changed()) {
msg_info("table has changed -- exiting");
exit(0);
}
}
/* main - pass control to the single-threaded skeleton */
int main(int argc, char **argv)
{
static CONFIG_STR_TABLE str_table[] = {
VAR_DEBUG_PEER_LIST, DEF_DEBUG_PEER_LIST, &var_debug_peer_list, 0, 0,
VAR_NOTIFY_CLASSES, DEF_NOTIFY_CLASSES, &var_notify_classes, 0, 0,
VAR_FALLBACK_RELAY, DEF_FALLBACK_RELAY, &var_fallback_relay, 0, 0,
VAR_BESTMX_TRANSP, DEF_BESTMX_TRANSP, &var_bestmx_transp, 0, 0,
VAR_ERROR_RCPT, DEF_ERROR_RCPT, &var_error_rcpt, 1, 0,
0,
};
static CONFIG_INT_TABLE int_table[] = {
VAR_SMTP_CONN_TMOUT, DEF_SMTP_CONN_TMOUT, &var_smtp_conn_tmout, 0, 0,
VAR_SMTP_HELO_TMOUT, DEF_SMTP_HELO_TMOUT, &var_smtp_helo_tmout, 1, 0,
VAR_SMTP_MAIL_TMOUT, DEF_SMTP_MAIL_TMOUT, &var_smtp_mail_tmout, 1, 0,
VAR_SMTP_RCPT_TMOUT, DEF_SMTP_RCPT_TMOUT, &var_smtp_rcpt_tmout, 1, 0,
VAR_SMTP_DATA0_TMOUT, DEF_SMTP_DATA0_TMOUT, &var_smtp_data0_tmout, 1, 0,
VAR_SMTP_DATA1_TMOUT, DEF_SMTP_DATA1_TMOUT, &var_smtp_data1_tmout, 1, 0,
VAR_SMTP_DATA2_TMOUT, DEF_SMTP_DATA2_TMOUT, &var_smtp_data2_tmout, 1, 0,
VAR_SMTP_QUIT_TMOUT, DEF_SMTP_QUIT_TMOUT, &var_smtp_quit_tmout, 1, 0,
VAR_DEBUG_PEER_LEVEL, DEF_DEBUG_PEER_LEVEL, &var_debug_peer_level, 1, 0,
0,
};
static CONFIG_BOOL_TABLE bool_table[] = {
VAR_SMTP_SKIP_4XX, DEF_SMTP_SKIP_4XX, &var_smtp_skip_4xx_greeting,
VAR_IGN_MX_LOOKUP_ERR, DEF_IGN_MX_LOOKUP_ERR, &var_ign_mx_lookup_err,
VAR_SKIP_QUIT_RESP, DEF_SKIP_QUIT_RESP, &var_skip_quit_resp,
0,
};
single_server_main(argc, argv, smtp_service,
MAIL_SERVER_INT_TABLE, int_table,
MAIL_SERVER_STR_TABLE, str_table,
MAIL_SERVER_BOOL_TABLE, bool_table,
MAIL_SERVER_PRE_INIT, pre_init,
MAIL_SERVER_PRE_ACCEPT, pre_accept,
0);
}
|