NAME Swaks - Swiss Army Knife SMTP, the all-purpose SMTP transaction tester DESCRIPTION Swaks' primary design goal is to be a flexible, scriptable, transaction-oriented SMTP test tool. It handles SMTP features and extensions such as TLS, authentication, and pipelining; multiple version of the SMTP protocol including SMTP, ESMTP, and LMTP; and multiple transport methods including UNIX-domain sockets, internet-domain sockets, and pipes to spawned processes. Options can be specified in environment variables, configuration files, and the command line allowing maximum configurability and ease of use for operators and scripters. QUICK START Deliver a standard test email to user@example.com on port 25 of test-server.example.net: swaks --to user@example.com --server test-server.example.net Deliver a standard test email, requiring CRAM-MD5 authentication as user me@example.com. An "X-Test" header will be added to the email body. The authentication password will be prompted for if it cannot be obtained from your .netrc file. swaks --to user@example.com --from me@example.com --auth CRAM-MD5 --auth-user me@example.com --header-X-Test "test email" Test a virus scanner using EICAR in an attachment. Don't show the message DATA part.: swaks -t user@example.com --attach - --server test-server.example.com --suppress-data '", "" is the argument to the "--quit-after" option. When used in the definition of an option, text that is inside of angle brackets ("<>") indicates a descriptive label for a value that the user should provide. For instance, "--quit-after " indicates that "" should be replaced with a valid stop-point value. [] When used in the definition of an option, text inside of square brackets ([]) indicates that the value is optional and can be omitted. For instance, "--to []" indicates that the "--to" option can be used with or without a specified "". OPTION PROCESSING To prevent potential confusion in this document a flag to Swaks is always referred to as an "option". If the option takes additional data, that additional data is referred to as an argument to the option. For example, "--from fred@example.com" might be provided to Swaks on the command line, with "--from" being the option and "fred@example.com" being "--from"'s argument. Options and arguments are the only way to provide information to Swaks. If Swaks finds data during option processing that is neither an option nor an option's argument, it will error and exit. For instance, if "--no-data-fixup 1" were found on the command line, this would result in an error because "--no-data-fixup" does not take an argument and therefore Swaks would not know what to do with 1. Options can be given to Swaks in three ways. They can be specified in a configuration file, in environment variables, and on the command line. Depending on the specific option and whether an argument is given to it, Swaks may prompt the user for the argument. When Swaks evaluates its options, it first looks for a configuration file (either in a default location or specified with "--config"). Then it evaluates any options in environment variables. Finally, it evaluates command line options. At each round of processing, any options set earlier will be overridden. Additionally, any option can be prefixed with "no-" to cause Swaks to forget that the variable had previously been set (either in an earlier round, or earlier in the same round). This capability is necessary because many options treat defined-but-no-argument differently than not-defined. As a general rule, if the same option is given multiple time, the last time it is given is the one that will be used. This applies to both intra-method (if "--from user1@example.com --from user2@example.com" is given, "user2@example.com" will be used) and inter-method (if "from user1@example.com" is given in a config file and "--from user2@example.com" is given on the command line, "user2@example.com" will be used) Each option definition ends with a parenthetical synopsis of how the option behaves. The following codes can be used Arg-None, Arg-Optional, Arg-Required These three codes are mutually exclusive and describe whether or not the option takes an argument. Note that this does not necessarily describe whether the argument is required to be specified directly, but rather whether an argument is required eventually. For instance, "--to" is labeled as Arg-Required, but it is legal to specify "--to" on the command line without an argument. This is because Swaks can prompt for the required argument if it is not directly provided. From-Prompt An option labeled with From-Prompt will prompt the user interactively for the argument if none is provided. From-File An option labeled with From-File will handle arguments as files in certain situations. If the initial argument is "-", the final argument is the contents of "STDIN". Multiple options can all specify "STDIN", but the same content will be used for each of them. If the initial argument is prefixed with "@", the argument will be treated as a path to a file. The file will be opened and the contents will be used as the final argument. If the contents of the file can't be read, Swaks will exit. To specify a literal string value starting with an "@", use two "@" symbols. The first will be stripped. It is not possible to include an unqualified file which starts with an "@" sign (like "--attach @file.txt" or "--attach @@file.txt"), but if you include a path to the file which splits up the two "@" signs, that will work (eg "--attach @./@file.txt" will include the contents of the file @file.txt). Sensitive If an option marked Sensitive attempts to prompt the user for an argument and the "--protect-prompt" option is set, Swaks will attempt to mask the user input from being echoed on the terminal. Swaks tries to mask the input in several ways, but if none of them work program flow will continue with unmasked input. Deprecated An option labeled Deprecated has been officially deprecated and will be removed in a future release. See the "DEPRECATIONS" section of this documentation for details about the deprecations. The exact mechanism and format for using each of the types is listed below. CONFIGURATION FILES A configuration file can be used to set commonly-used or abnormally verbose options. By default, Swaks looks in order for $SWAKS_HOME/.swaksrc, $HOME/.swaksrc, and $LOGDIR/.swaksrc. If one of those is found to exist (and "--config" has not been used) that file is used as the configuration file. Additionally, a configuration file in a non-default location can be specified using "--config". If this is set and not given an argument Swaks will not use any configuration file, including any default file. If "--config" points to a readable file, it is used as the configuration file, overriding any default that may exist. If it points to a non-readable file an error will be shown and Swaks will exit. A set of "portable" defaults can also be created by adding options to the end of the Swaks program file. As distributed, the last line of Swaks should be "__END__". Any lines added after "__END__" will be treated as the contents of a configuration file. This allows a set of user preferences to be automatically copied from server to server in a single file. If configuration files have not been explicitly turned off, the "__END__" config is always read. Only one other configuration file will ever be used per single invocation of Swaks, even if multiple configuration files are specified. If the "__END__" config and another config are to be read, the "__END__" config will be processed first. Specifying the "--config" option with no argument turns off the processing of both the "__END__" config and any actual config files. In a configuration file lines beginning with a hash ("#") are ignored. All other lines are assumed to be an option to Swaks, with the leading dash or dashes optional. Everything after an option line's first space is assumed to be the option's argument and is not shell processed. Therefore, quoting is usually unneeded and will be included literally in the argument. There is a subtle difference between providing an option with no argument and providing an option with an empty argument. If an option line does not have a space, the entire line is treated as an option and there is no argument. If the line ends in a single space, it will be processed as an option with an empty argument. So, "apt" will be treated as "--apt", but "apt " will be treated as "--apt ''". Here is an example of the contents of a configuration file: # always use this sender, no matter server or logged in user --from fred@example.com # I prefer my test emails have a pretty from header. Note # the lack of dashes on option and lack of quotes around # entire argument. h-From: "Fred Example" Options specific to configuration file: --config [] This option provides a path to a specific configuration file to be used. If specified with no argument, no automatically-found configuration file (via $HOME, etc, or "__END__") will be processed. If the argument is a valid file, that file will be used as the configuration file (after "__END__" config). If argument is not a valid, readable file, Swaks will error and exit. This option can be specified multiple times, but only the first time it is specified (in environment variable and the command line search order) will be used. (Arg-Optional) CONFIGURATION ENVIRONMENT VARIABLES Options can be supplied via environment variables. The variables are in the form $SWAKS_OPT_name, where "name" is the name of the option that would be specified on the command line. Because dashes aren't allowed in environment variable names in most UNIX-ish shells, no leading dashes should be used and any dashes inside the option's name should be replaced with underscores. The following would create the same options shown in the configuration file example: $ SWAKS_OPT_from='fred@example.com' $ SWAKS_OPT_h_From='"Fred Example" ' Setting a variable to an empty value is the same as specifying it on the command line with no argument. For instance, setting would cause Swaks to prompt the user for the server to which to connect at each invocation. On Windows, it is not possible to set empty environment variables. The behavior can be simulated by setting the environment variable to "<>" instead. Additionally, embedding the header name in the header option via environment variable is not allowed on Windows (eg "SWAKS_OPT_header_Foo=bar" will result in an error, but "SWAKS_OPT_header="Foo: bar"" will work.) Because there is no inherent order in options provided by setting environment variables, the options are sorted before being processed. This is not a great solution, but it at least defines the behavior, which would be otherwise undefined. As an example, if both $SWAKS_OPT_from and $SWAKS_OPT_f were set, the value from $SWAKS_OPT_from would be used, because it sorts after $SWAKS_OPT_f. Also as a result of not having an inherent order in environment processing, unsetting options with the "no-" prefix is unreliable. It works if the option being turned off sorts before "no-", but fails if it sorts after. Because "no-" is primarily meant to operate between config types (for instance, unsetting from the command line an option that was set in a config file), this is not likely to be a problem. In addition to setting the equivalent of command line options, $SWAKS_HOME can be set to a directory containing the default .swaksrc to be used. COMMAND LINE OPTIONS The final method of supplying options to Swaks is via the command line. The options behave in a manner consistent with most UNIX-ish command line programs. Many options have both a short and long form (for instance "-s" and "--server"). By convention short options are specified with a single dash and long options are specified with a double-dash. This is only a convention and either prefix will work with either type. The following demonstrates the example shown in the configuration file and environment variable sections: $ swaks --from fred@example.com --h-From: '"Fred Example" ' TRANSPORTS Swaks can connect to a target via UNIX pipes ("pipes"), UNIX domain sockets ("UNIX sockets"), or internet domain sockets ("network sockets"). Connecting via network sockets is the default behavior. Because of the singular nature of the transport used, each set of options in the following section is mutually exclusive. Specifying more than one of "--server", "--pipe", or "--socket" will result in an error. Mixing other options between transport types will only result in the irrelevant options being ignored. Below is a brief description of each type of transport and the options that are specific to that transport type. NETWORK SOCKETS This transport attempts to deliver a message via TCP/IP, the standard method for delivering SMTP. This is the default transport for Swaks. If none of "--server", "--pipe", or "--socket" are given then this transport is used and the target server is determined from the recipient's domain (see "--server" below for more details). This transport requires the IO::Socket::IP module for both IPv4 and IPv6 sockets. If this module is not loadable, Swaks will attempt to use the IO::Socket library for IPv4 and IO::Socket::INET6 for IPv6 support. Attempting to use this transport with none of those libraries available will result in an error and program termination. The fall back to IO::Socket and IO::Socket::INET6 is deprecated and will be removed in a future release. See DEPRECATIONS below -s, --server [[:]] Explicitly tell Swaks to use network sockets and specify the hostname or IP address to which to connect, or prompt if no argument is given. If this option is not given and no other transport option is given, the target mail server is determined from the appropriate DNS records for the domain of the recipient email address using the Net::DNS module. If Net::DNS is not available Swaks will attempt to connect to localhost to deliver. The target port can optionally be set here. Supported formats for this include SERVER:PORT (supporting names and IPv4 addresses); [SERVER]:PORT and SERVER/PORT (supporting names, IPv4 and IPv6 addresses). A port set via this option will only be used if the "--port" option is not used. See also "--copy-routing". (Arg-Required, From-Prompt) -p, --port [] Specify which TCP port on the target is to be used, or prompt if no argument is listed. The argument can be a service name (as retrieved by getservbyname(3)) or a port number. The default port is smtp/25 unless influenced by the "--protocol" or "--tls-on-connect" options. (Arg-Required, From-Prompt) -li, --local-interface [[:]] Use argument as the local interface for the outgoing SMTP connection, or prompt user if no argument given. Argument can be an IP address or a hostname. Default action is to let the operating system choose the local interface. See "--server" for additional comments on : format. A port set via this option will only be used if the "--port" option is not used. (Arg-Required, From-Prompt) -lp, --local-port, --lport [] Specify the outgoing port from which to originate the transaction. The argument can be a service name (as retrieved by getservbyname(3)) or a port number. If this option is not specified the system will pick an ephemeral port. Note that regular users cannot specify some ports. (Arg-Required, From-Prompt) --copy-routing The argument is interpreted as the domain part of an email address and it is used to find the target server using the same logic that would be used to look up the target server for a recipient email address. See "--to" option for more details on how the target is determined from the email domain. (Arg-Required) -4, -6 Force IPv4 or IPv6. (Arg-None) UNIX SOCKETS This transport method attempts to deliver messages via a UNIX-domain socket file. This is useful for testing MTA/MDAs that listen on socket files (for instance, testing LMTP delivery to Cyrus). This transport requires the IO::Socket::UNIX module which is part of the standard Perl distribution. If this module is not loadable, attempting to use this transport will result in an error and program termination. --socket [] This option takes as its argument a UNIX-domain socket file. If Swaks is unable to open this socket it will display an error and exit. (Arg-Required, From-Prompt) PIPES This transport attempts to spawn a process and communicate with it via pipes. The spawned program must be prepared to behave as a mail server over "STDIN"/"STDOUT". Any MTA designed to operate from inet/xinet should support this. In addition, some MTAs provide testing modes that can be communicated with via "STDIN"/"STDOUT". This transport can be used to automate that testing. For example, if you implemented DNSBL checking with Exim and you wanted to make sure it was working, you could run "swaks --pipe "exim -bh 127.0.0.2"". Ideally, the process you are talking to should behave exactly like an SMTP server on "STDIN" and "STDOUT". Any debugging should be sent to "STDERR", which will be directed to your terminal. In practice, Swaks can generally handle some debug on the child's "STDOUT", but there are no guarantees on how much it can handle. This transport requires the IPC::Open2 module which is part of the standard Perl distribution. If this module is not loadable, attempting to use this transport will result in an error and program termination. --pipe [] Provide a process name and arguments to the process. Swaks will attempt to spawn the process and communicate with it via pipes. If the argument is not an executable Swaks will display an error and exit. (Arg-Required, From-Prompt) PROTOCOL OPTIONS These options are related to the protocol layer. -t, --to [[,[,...]]] --cc [[,[,...]]] --bcc [[,[,...]]] These options all tell Swaks to use the argument(s) as the envelope-recipient for the email. There are subtle differences between these three options, detailed below. If any option is specified but with no arguments, Swaks will prompt the user for an argument. "--to" is special in that it is the only option required by Swaks. There is no default value for this option. If no recipients are provided via any means, user will be prompted to provide one interactively. The only exception to this is if a "--quit-after" value is provided which will cause the SMTP transaction to be terminated before the recipient is needed. If multiple recipients are provided and the recipient domain is needed to determine routing, the domain of the last recipient in the "--to" argument list is used. The primary distinction between these options is how their arguments are treated when generating the DATA portion of the email. They each have their own replacement tokens ("%TO_ADDRESS%", "%CC_ADDRESS%", and "%BCC_ADDRESS%" respectively) which can be used by anyone crafting a custom DATA. In Swaks' default message, "%TO_ADDRESS%" will be used for the To: header and, if it is populated, "%CC_HEADER%" will be used for a Cc: header. "%BCC_ADDRESS%" is not used in the default DATA. (Arg-Required, From-Prompt) -f, --from [] Use argument as envelope-sender for email, or prompt user if no argument specified. The string "<>" can be supplied to mean the null sender. If user does not specify a sender address a default value is used. The domain-part of the default sender is a best guess at the fully-qualified domain name of the local host. The method of determining the local-part varies. If the $LOGNAME environment variable is set, it will be used as the local-part. Otherwise the value from "Win32::LoginName()" will be used on Windows and getpwuid(3) on UNIX-ish platforms. See also "--force-getpwuid". If Swaks cannot determine a local hostname and the sender address is needed for the transaction, Swaks will error and exit. In this case, a valid string must be provided via this option. (Arg-Required, From-Prompt) --ehlo, --lhlo, -h, --helo [] String to use as argument to HELO/EHLO/LHLO command, or prompt user if no argument is specified. If this option is not used a best guess at the fully-qualified domain name of the local host is used. If Swaks cannot determine a local hostname and the helo string is needed for the transaction, Swaks will error and exit. In this case, a valid string must be provided via this option. (Arg-Required, From-Prompt) -q, --quit, --quit-after Point at which the transaction should be stopped. When the requested stopping point is reached in the transaction, and provided that Swaks has not errored out prior to reaching it, Swaks will send "QUIT" and attempt to close the connection cleanly. These are the valid arguments and notes about their meaning. (Arg-Required) PROXY Quit after the server sends a response to a PROXY request. Note that if there is not an error negotiating proxy, this will be synonymous with CONNECT. CONNECT, BANNER Terminate the session after receiving the greeting banner from the target. FIRST-HELO, FIRST-EHLO, FIRST-LHLO In a STARTTLS (but not tls-on-connect) session, terminate the transaction after the first of two HELOs. In a non-STARTTLS transaction, behaves the same as HELO (see below). XCLIENT Quit after XCLIENT is negotiation. This always quits after the point where XCLIENT would have been negotiated, regardless of whether it was attempted. XCLIENT-HELO Quit after the HELO that XCLIENT negotiation triggers. This differs from HELO and FIRST-HELO because XCLIENT negotiation can happen at multiple points in the SMTP transaction and it is impossible to specifically refer to the XCLIENT-triggered HELO using the HELO or FIRST-HELO stop-points. This always quits after the point where the XCLIENT-triggered HELO would have occurred, regardless of whether it was attempted. STARTTLS, TLS Quit the transaction immediately following TLS negotiation. Note that this happens in different places depending on whether STARTTLS or tls-on-connect are used. This always quits after the point where TLS would have been negotiated, regardless of whether it was attempted. HELO, EHLO, LHLO In a STARTTLS or XCLIENT session, quit after the second HELO. Otherwise quit after the first and only HELO. AUTH Quit after authentication. This always quits after the point where authentication would have been negotiated, regardless of whether it was attempted. MAIL, FROM Quit after MAIL FROM: is sent. RCPT, TO Quit after RCPT TO: is sent. --da, --drop-after The option is similar to "--quit-after", but instead of trying to cleanly shut down the session it simply terminates the session. This option accepts the same stop-points as "--quit-after" and additionally accepts DATA and DOT, detailed below. (Arg-Required) DATA Drop the connection after DATA is sent by server. DOT Drop the connection after the final '.' of the message is sent by server. --das, --drop-after-send This option is similar to "--drop-after", but instead of dropping the connection after reading a response to the stop-point, it drops the connection immediately after sending stop-point. It accepts the same stop-points as "--drop-after". If the stop-point is for an optional part of the transaction which is not actually sent (for instance STARTTLS or AUTH), this option will behave identically to "--drop-after". See below for specific details. (Arg-Required) CONNECT Connect to the server and then drops the connection before receiving the server's banner. STARTTLS, TLS Behaves identically to "--drop-after". HELO, EHLO, LHLO Doesn't necessarily work as expected. If it appears to read the HELO response incorrectly, use FIRST-HELO instead. --timeout [