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.

Reply via email to