I am not opposed to making bounces thread-friendly, but I wonder, Postfix includes a copy of the undelivered message, why is it difficult to find out what message was not delivered? Are mail systems routinely deleting that information, because spam?
The code is not bad for a rusty C programmer. However, I see a new vstring_alloc() call without a corresponding vstring_free(). I don't think that you should change the code that handles the case of "no sender record before message content". This already was delicate code, and changing it is likely to introduce a bug. It will greatly increase my time for code review (first to determine that the old code is correct, and then to determine that the new code does not break the old code). Extracting headers from a record stream is tricky. Unlikely as it may be, your code may see message-id: in the middle of a long physical line (which Postfix stores as one or more REC_TYPE_CONT records followed by REC_TYPE_NORM, each of which could start with message-id:). For comparison, I looked at code that I wrote to extract Delivered-To headers, and that code misses information when some header is very long (does not handle REC_TYPE_CONT). Extracting headers correctly requires a state variable that remembers whether the last record came from the beginning of a line. The only Postfix code that handles long headers correctly is in the Postfix MIME parser (which contains such a state variable); the cleanup daemon uses that to extract header information. Some of that information ends up in the Postfix queue file segment for extracted information. We could use that to extract the message-id. Anyway, this is Monday, and it will be a few days before I can do a weekend project. Wietse