On Tue, Sep 28, 2010 at 03:46:17PM -0700, Murray S. Kucherawy wrote: > No, I didn't test it, because I don't have postfix installed anywhere > here. But even testing it doesn't mean my experiment nailed down the > actual source code logic or the background for it, hence the question. >
The second comment paragraph may be a bit unclear. It says that inserting a blank line after primary headers does not break anything, not that we don't insert a blank line. Either way, the Postfix MIME parser ends up in the BODY state, but the BODY_OUT(state, REC_TYPE_NORM, "", 0) code to add blank line is only called at the end of the primary header. /* * Invalid input. Force output of one blank line and jump to the * body state, leaving all other state alone. * * We don't break legitimate mail by inserting a blank line * separator between primary headers and a non-empty body. Many * MTA's don't even record the presence or absence of this * separator, nor does the Milter protocol pass it on to Milter * applications. * * XXX We don't insert a blank line separator into attachments, to * avoid breaking digital signatures. Postfix shall not do a * worse mail delivery job than MTAs that can't even parse MIME. * We switch to body state anyway, to avoid treating body text as * header text, and mis-interpreting or truncating it. The code * below for initial From_ lines is for educational purposes. * * Sites concerned about MIME evasion can use a MIME normalizer. * Postfix has a different mission. */ else { if (msg_verbose) msg_info("garbage in %s header", state->curr_state == MIME_STATE_MULTIPART ? "multipart" : state->curr_state == MIME_STATE_PRIMARY ? "primary" : state->curr_state == MIME_STATE_NESTED ? "nested" : "other"); switch (state->curr_state) { case MIME_STATE_PRIMARY: BODY_OUT(state, REC_TYPE_NORM, "", 0); SET_CURR_STATE(state, MIME_STATE_BODY); break; #if 0 case MIME_STATE_NESTED: if (state->body_offset <= 1 && rec_type == REC_TYPE_NORM && len > 7 && (strncmp(text + (*text == '>'), "From ", 5) == 0 || strncmp(text, "=46rom ", 7) == 0)) break; /* FALLTHROUGH */ #endif default: SET_CURR_STATE(state, MIME_STATE_BODY); break; } } -- Viktor.