Skip to content

Handle lines longer than 1000 bytes: error "bad mail input format" #18

Open

Description

@blueyed

Currently dma chokes on mail input which contains lines longer than 1000 bytes, because of the buffer being used.
When it does not find a newline at the end, it adds one, but then assumes/requires this to be the last line.

The error is "bad mail input format".

This might happen when using dma to handle web application errors during development / local setup, and the included debug information contains huge environment etc settings (e.g. "LS_COLORS").

I think that it would be saner to not require RFC2822 compliance, but accept the mail nonetheless.

The code in question: https://github.com/corecode/dma/blob/master/mail.c#L376

Activity

  1. corecode commented on Jan 11, 2014

    @corecode
    Owner

    Do you have a suggestion how to deal with longer lines? Something that
    does not complicate the code?

    On 01/11/2014 07:00 AM, Daniel Hahler wrote:

    Currently dma chokes on mail input which contains lines longer than
    1000 bytes, because of the buffer being used.
    When it does not find a newline at the end, it adds one, but then
    assumes/requires this to be the last line.

    The error is "bad mail input format".

    This might happen when using dma to handle web application errors
    during development / local setup, and the included debug information
    contains huge environment etc settings (e.g. "LS_COLORS").

    I think that it would be saner to not require RFC2822 compliance, but
    accept the mail nonetheless.

    The code in question:
    https://github.com/corecode/dma/blob/master/mail.c#L376

    —
    Reply to this email directly or view it on GitHub
    #18.

  2. blueyed commented on Jan 11, 2014

    @blueyed
    ContributorAuthor

    The easiest approach would probably be to increase the buffer length, from 1000 bytes to maybe 64kB (65536).
    It would/could then still fail in the same way, but it's much more unlikely.

    Or, just do not add a newline (and effectively aborting / cutting the input) and keep reading in 1000 byte chunks.

  3. corecode commented on Jan 12, 2014

    @corecode
    Owner

    The RFC is absolutely clear on this issue:

    Each line of characters MUST be no more than 998 characters
    

    and
    However, there are so many implementations that (in compliance with
    the transport requirements of [RFC5321
    http://tools.ietf.org/search/rfc5321]) do not accept messages
    containing more than 1000 characters including the CR and LF per line,
    it is important for implementations not to create such messages.

    It is clear that we can not forward any message with more than 1000
    characters per line. What do you suggest as alternative? Insert a
    linebreak after 998 characters?

    On 01/11/2014 11:15 PM, Daniel Hahler wrote:

    The easiest approach would probably be to increase the buffer length,
    from 1000 bytes to maybe 64kB (65536).
    It would/could then still fail in the same way, but it's much more
    unlikely.

    Or, just do not add a newline (and effectively aborting / cutting the
    input) and keep reading in 1000 byte chunks.

    —
    Reply to this email directly or view it on GitHub
    #18 (comment).

  4. blueyed commented on Jan 12, 2014

    @blueyed
    ContributorAuthor

    Well, I think that dma is not creating the message, but only transports it.

    The bug is really with the app that hands it over to dma.

    Inserting newlines can be very problematic, if the message is meant to contain (encoded) data, and the result may fail to parse afterwards.

    Imagine an automated message, with "key=value" pairs on separate lines, where it may result in "key=verylongvalue\r\nstillvalue".

    However, breaking lines after 998 bytes is still far better than rejecting the mail altogether.

    I can imagine having a configuration option (in dma.conf) for this: RFC2822_SPLITLINES.
    If set, CRLF gets inserted after 998 bytes, otherwise the lines would get bypassed unchanged.

  5. corecode commented on Jan 12, 2014

    @corecode
    Owner

    It is not optional to forward messages with more than 998 characters per
    line: it is forbidden. Do you know how other MTAs handle this? I only
    see two options: break line, or reject (bounce).

    On 01/12/2014 06:01 PM, Daniel Hahler wrote:

    Well, I think that dma is not creating the message, but only
    transports it.

    The bug is really with the app that hands it over to dma.

    Inserting newlines can be very problematic, if the message is meant to
    contain (encoded) data, and the result may fail to parse afterwards.

    Imagine an automated message, with "key=value" pairs on separate
    lines, where it may result in "key=verylongvalue\r\nstillvalue".

    However, breaking lines after 998 bytes is still far better than
    rejecting the mail altogether.

    I can imagine having a configuration option (in dma.conf) for this:
    RFC2822_SPLITLINES.
    If set, CRLF gets inserted after 998 bytes, otherwise the lines would
    get bypassed unchanged.

    —
    Reply to this email directly or view it on GitHub
    #18 (comment).

  6. blueyed commented on Jan 12, 2014

    @blueyed
    ContributorAuthor

    Then breaking the line is better than rejecting the mail.

    Postfix has a line_length_limit option, with a default of 2048 (http://www.postfix.org/postconf.5.html):

    Upon input, long lines are chopped up into pieces of at most this length; upon delivery, long lines are reconstructed.

    It sounds like this will effectively pass through long lines?!

  7. bcoca commented on Mar 26, 2014

    @bcoca

    @blueyed, IIRC that limit is for internal processing across Postfix apps and filters, for actual smtp this is the setting:
    http://www.postfix.org/postconf.5.html#smtp_line_length_limit

  8. corecode commented on Mar 26, 2014

    @corecode
    Owner

    Good catch. Any suggestions how we should handle this?

    On 03/26/2014 08:24 PM, Brian Coca wrote:

    @blueyed https://github.com/blueyed, IIRC that limit is for internal
    processing across Postfix apps and filters, for actual smtp this is
    the setting:
    http://www.postfix.org/postconf.5.html#smtp_line_length_limit

    —
    Reply to this email directly or view it on GitHub
    #18 (comment).

  9. bcoca commented on Mar 26, 2014

    @bcoca

    I think rejection is OK, but maybe add more info to the message, 'bad mail input format' (I just ran into this) is a bit too succinct, knowing that its a line length error helps pinpoint the issue much faster. Also, quoting RFC helps convince programmers change their code vs demand that the MTA just accept their emails.

  10. corecode commented on Mar 26, 2014

    @corecode
    Owner

    alternatively we could force a linebreak when accepting the mail, like
    postfix does when sending?

    On 03/26/2014 08:47 PM, Brian Coca wrote:

    I think rejection is OK, but maybe add more info the the message, 'bad
    mail input format' (I just ran into this) is a bit too succinct,
    knowing that its a line length error helps pinpoint the issue much
    faster. Also, quoting RFC helps convince programmers change their code
    vs demand that the MTA just accept their emails.

    —
    Reply to this email directly or view it on GitHub
    #18 (comment).

  11. blueyed commented on Mar 27, 2014

    @blueyed
    ContributorAuthor

    The Postfix approach seems sensible.
    To me everything is better than rejecting the mail.

    quoting RFC helps convince programmers change their code

    I agree. There could be a warning instead of the current error.

    Given the use case of dma (for personal or lightweight use in containers) I do not think it should be too strict (i.e. rejecting the mail).

  12. bcoca commented on Mar 27, 2014

    @bcoca

    I disagree, I use dma because it it simple and lightweight and doesn't try to do complex stuff like line splitting with character or armor encodings. If it accepts mail and it then gets rejected by another mailer, it creates more issues than it solves.

    I am a fan of fail early and fail loudly, if you start accepting emails and push the problem downstream you never have an incentive to fix the actual issue, the program composing non compliant smtp messages.

  13. emaste commented on Mar 24, 2016

    @emaste
    Collaborator

    This is one issue that prevented the FreeBSD clusteradm team switching to DMA internally: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=208261

  14. 28 remaining items

  15. corecode commented on Feb 3, 2022

    @corecode
    Owner

    I think we can keep the feof() loop condition, but just do something about error return from getline.

  16. emaste commented on Feb 3, 2022

    @emaste
    Collaborator

    I think it's fine to use getline()'s -1 return

    I have a FreeBSD review in https://reviews.freebsd.org/D34159

  17. ant5 commented on Jun 21, 2023

    @ant5

    Hello!

    After switching to dma for local delivery and few monthes of things going well I've got an error "bad mail input format" with one email message.

    Does I understand right that there is a patch of cure and this patch is only in FreeBSD 13+ source tree?

    How can I cure this?
    Does I need to extract somehow this patch(es) from FreeBSD source and create custom port for mail/dma then add those patches to the custom port and then make custom package?

    Can someone guide me to eliminate future accidents?

    P.S. My system is FreeBSD 12-STABLE. Dma is mostly invoked by sieve scripts for coping/forwarding.

  18. corecode commented on Jun 21, 2023

    @corecode
    Owner

    Are you submitting an incorrectly formatted message? The correct fix would be to only submit correctly formatted messages.

  19. ant5 commented on Jun 21, 2023

    @ant5

    One user (who is in company management) sended email to other users. Email message seems very casual.

    But then he got email back:
    I'm sorry to have to inform you that your message could not be delivered to one or more recipients. ... <[X@Z](mailto:X@Z)>: host 127.0.6.1[127.0.6.1] said: 451 4.2.0 <[X@Z](mailto:X@Z)> Execution of Sieve filters was aborted due to temporary failure (in reply to end of DATA command) ...
    for those users who have configured copying/redirecting via sieve scripts.

    The log say:
    Jun 20 21:49:37 mail dma[e98a03][8169]: bad mail input format: from pop (uid 68) (envelope-from X@Z)

  20. corecode commented on Jun 21, 2023

    @corecode
    Owner

    I would need to see the message to understand what happened. With the log messages it is not clear what happened. How are pop, sieve, dma, and the user related?

  21. ant5 commented on Jun 21, 2023

    @ant5

    Technicaly speaking, user work on workstation with some email client. Email client sent message to postfix via SMTP. Postfix relay message to dovecot via LMTP. Dovecote execute sieve script. Sieve script invoke mailwrapper (sendmail). Mailwrapper execute dma.

    I have this message extracted from bounce email but I don't know is it in virgin form and will it raise an error.

  22. corecode commented on Jun 21, 2023

    @corecode
    Owner

    That is a complicated setup. Why are you using dma and not postfix for dovecot for delivery? Without the original mail delivered to dma we don't know what is going on - it seems that it passed through several MTAs, so the assumption should be that the mail was formatted correctly. This pretty much rules out a 1000+ byte header line.

  23. ant5 commented on Jun 21, 2023

    @ant5

    Why are you using dma and not postfix for dovecot for delivery?

    They all in separate jails. Dma in dovecot jail will relay to postfix in other jail (host).

  24. ant5 commented on Jun 21, 2023

    @ant5

    I'll try to invoke dma and feed it problematic message...
    But it's not so simple for me.

  25. ant5 commented on Jun 21, 2023

    @ant5

    Yes. The message gives an error.

    Zipped and attached:
    < deleted confidentional data >

  26. corecode commented on Jun 21, 2023

    @corecode
    Owner

    Thank you. The problem is that one line is exactly 1000 bytes long including the \r\n.

  27. haarp commented on Jan 4, 2024

    @haarp

    Wouldn't a config option setting the max buffer size/line length be the easiest solution here? Yes, it would break the spec, but it would be up to the admin to decide that. And for local-only delivery, there are no other servers further down the line that might choke on it.

    Splitting is also a decent solution, but not always desireable. Some content, like code or logs shouldn't be split, to retain proper syntax.

    Relegating this to the mail producer is also not always an option. They can be unpredictable. Maybe there was an error during a cronjob and it prints an unpredictably long line. The admin would get no mail, and very likely not realize.

  28. corecode commented on Jan 6, 2024

    @corecode
    Owner

    we definitely don't want to break the spec. if there is a line >1000 chars, we either have to split it or reject it outright. we can't pass on an invalid message.

  29. kgcgs commented on Sep 11, 2024

    @kgcgs

    The only correct thing to do here is mimic the behavior of the fully featured MTAs. Sendmail has always split long lines in order to enforce compliance in messages that it creates but happily passes messages with long lines through SMTP without molesting them. Failure to address this in dma is just going to lead to messages being lost unexpectedly which is how most of us probably got here in the first place. Seems like an easy fix? (Even if it's a part of the RFC that's likely completely unnecessary to respect.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions