# Transports

This directory contains Perl transport scripts that take the generated report and deliver it to a destination (HTTP, email, or local file). The order and the choice of transports is defined in the configuration file under the `transports` key. (Before v3.8.0 this directory was called `scripts/`; the config key that lists the directories is still named `scriptDirs`.)

## Rules for a transport

- A transport must be Perl, and must define a subroutine named `doit` accepting two parameters: a hash reference with the parameters the transport needs (the transport's own entry in the config file, plus the values the client adds, see below) and a string containing the data to be transmitted.
- `doit` returns 1 on success. Any other return value is a failure; the client logs it and tries the next transport. The client stops at the first transport that returns 1. If none succeeds, it logs the failure and prints the report to STDOUT (cron mails it).
- The report string is already UTF-8 encoded bytes. Write or send it as-is; do not add an encoding layer of your own, or non-ASCII text is encoded twice.
- Values the client adds to every transport's parameters: `upload_type`, `data version`, `report date`, `client name`, `host name`, `serial number`, `UUID`; `fileType` may be added.
- Transports run in numeric order of their keys under `transports` in the config file. Each entry names its script in `sendScript`.
- The installer sets the files in this directory to owner root, mode 0700.
- If you write your own, put it in `<confdir>/transports` to avoid overwriting on upgrade (v3.7.1 used `<confdir>/scripts`; the installer renames it when upgrading).

## Script inventory

### save_local

Saves the report locally. Even on systems where another transport is preferred, this should be defined in the config file with an index larger than everything else, so a copy is kept when the others fail. The target directory is defined in the config file with the key `output directory`. The target file name is built by joining `report date`, `client name`, `host name` and `serial number` with underscores (spaces, colons and slashes become underscores), then `.sysinfo`, then the file type.

### send_local_smtp

Sends the report by e-mail through the local mail system: it pipes a complete message (headers, UTF-8 body, optional attachment) to the `sendmail`-compatible program on the host (sendmail, msmtp, postfix, exim, FreeBSD's sendmail or dma). No credentials are read, so a host that can use it needs no SMTP password in its config. Needs only core Perl.

Parameters: `mailTo` (required; several addresses may be separated by commas, semicolons or spaces). Optional: `mailFrom`, `mailCC`, `mailBCC`, `mailSubject`, `attachment` (path of a file to attach), `sendmailPath` (default: searched for in `/usr/sbin`, `/usr/lib`, `/usr/local/sbin`, `/usr/bin`, `/usr/local/bin`).

Returns 1 on success; 2 `mailTo` missing; 3 no sendmail program; 4 could not start it or attachment unreadable; 100 plus the exit status when sendmail fails (never 1, which would read as success). A queueing MTA (full sendmail, postfix) returns success once the message is queued, so a later delivery failure is not seen by the client; keep `save_local` as the last transport. msmtp sends synchronously, so its failures are seen.

### send_auth_smtp

Sends the report directly to an SMTP server with optional authentication and TLS. Meant to follow `send_local_smtp` in the transport order, so only the hosts that need it carry `smtpUser` and `smtpPass`.

Parameters: `mailServer` (`host` or `host:port`, port 25 by default; required), `mailTo` (required). Optional: `mailFrom` (default `smtpUser`), `mailCC`, `mailBCC`, `mailSubject`, `attachment`, `smtpUser`, `smtpPass`, `tls`. `tls` is `auto` (the default: implicit TLS on port 465, otherwise STARTTLS when the server offers it), `yes` (TLS required) or `no`. Credentials are never sent over an unencrypted connection unless `tls` is `no`.

Perl modules: `Net::SMTP` (core); `IO::Socket::SSL` unless `tls: no`; `Authen::SASL` when `smtpUser` is set. If one is missing, `doit` dies with a message naming it (the client logs it and tries the next transport); it does not fall back to something weaker. Install them with the package manager (Debian `libio-socket-ssl-perl libauthen-sasl-perl`, FreeBSD `p5-IO-Socket-SSL p5-Authen-SASL`).

Returns 1 on success; 2 `mailServer` or `mailTo` missing; 3 could not connect; 4 TLS required but not available; 5 authentication failed; 6 server rejected the message; 7 attachment unreadable.

Example order: `0` `upload_http`, `1` `send_local_smtp`, `2` `send_auth_smtp`, `3` `save_local`.

### upload_http

Uploads the report to a CGI script by multipart HTTP POST (a sample receiver, `upload_file.php`, with `test_upload.html` to test the transport by hand, is in the `server/` directory).

Parameters: `URL` (URL of the upload script to send the file to).

Keys which are matched to the `<INPUT>` names on the upload form of the sample script (each one must be given, or `doit` returns a non-1 code):

- `key for client`: client
- `key for date`: report_date
- `key for hostname`: hostname
- `key for report`: report
- `key for serial number`: serialnumber

## Usage

Example transport invocation from a Perl one-liner using the same interface as the client:

```bash
perl -I.. -e 'require "./save_local"; my $p={"output directory"=>"/tmp","report date"=>"2026-10-11 00:00:00","client name"=>"Example","host name"=>"host.example","serial number"=>"ABC123","fileType"=>"yaml"}; print doit($p,"---\nreport:\n  version: v3.8.0\n");'
```

Example full client run using configured transport priorities (as root, from the client directory):

```bash
./sysinfo_client --config sysinfo_client.yaml
```

For unattended execution, schedule only the main client command; it handles transport ordering and fallback to STDOUT when no transport succeeds.
