open
https://gitlab.synchro.net/main/sbbs/-/issues/1226
Two related defects in the POP3 server's handling of file attachments (`src/sbbs3/mailsrvr.cpp`), found while investigating a
`!ERROR opening/encoding/sending` in `data/error.log`.
### 1. `TOP` transmits attachments, and deletes them
`TOP` and `RETR` share `sockmsgtxt()` / `sockmimetext()`, and the `maxlines` argument bounds **only** the body-text loop. The attachment loop that follows it is unguarded, so `TOP <n> 0` — a headers-only preview — MIME-encodes and transmits the entire attachment, and on success `remove()`s the file when `MSG_KILLFILE` is set.
RFC 1939 defines `TOP` as the headers, a blank line, and the first *n* lines
of the body. Sending a multi-megabyte attachment to a client that asked for zero body lines is wrong on its own; destroying the file during a preview is data loss. A client that sweeps the mailbox with `TOP n 0` before deciding
what to `RETR` will consume every kill-file attachment in the preview pass and then deliver an empty MIME part on the `RETR` that follows.
The `tls_dkim_cap` guard on the same `remove()` call is the identical failure mode already handled for one caller (the DKIM sign/send two-pass), where rendering a message twice deleted the file on the first pass.
### 2. `MSG_FILEATTACH` survives the kill-file removal
After a successful `RETR` the attachment file is removed, but the message keeps `MSG_FILEATTACH | MSG_KILLFILE` in its header and stays in the mailbox. Every subsequent fetch of that message re-attempts the attachment against a file that the earlier fetch deleted, and logs:
```
mail 4400 POP3 !ERROR opening/encoding/sending s:\sbbs\data\file/0614.in/new_textures.png
```
Any client configured to leave mail on the server hits this on its next poll. With two clients on one mailbox it is unavoidable — whichever polls second never receives the attachment at all.
### Observed sequence
One local message, `MSG_FILEATTACH | MSG_KILLFILE` (`auxattr` 0x0a), attached via the Terminal Server; mailbox polled by two clients against two hosts sharing the mail base:
| Time (2026-08-11) | Server | Command | Result |
|---|---|---|---|
| 02:24:36 | Linux | `RETR 857` | attachment sent, file removed |
| 18:10:30 | Windows | `TOP 857 0` | file missing, error logged |
| 18:11:14 | Windows | `RETR 857` | file missing, error logged |
The message's `auxattr` is still 0x0a afterwards; nothing clears it.
### Suggested fix
1. Propagate the partial-fetch state into `sockmimetext()` and skip the
attachment loop entirely when the client issued `TOP` (`maxlines != -1`).
2. Clear `MSG_FILEATTACH` (and `MSG_KILLFILE`) from the header once the
`remove()` succeeds. The POP3 path already rewrites the header there to set
`MSG_READ`.
— *Authored by Claude (Claude Code), on behalf of @rswindell*
--- SBBSecho 3.37-Linux
* Origin: Vertrauen - [vert/cvs/bbs].synchro.net (1:103/705)