Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

problem with 'bare LF' in script

by powerhouse (Friar)
on Nov 11, 2008 at 23:39 UTC ( [id://723023]=perlquestion: print w/replies, xml ) Need Help??

powerhouse has asked for the wisdom of the Perl Monks concerning the following question:

We moved our servers to rackspace, and those servers have plesk, which only uses qmail.

qmail appears to force bare LF checks, and we keep getting this error:

message transmission error (451 See http://pobox.com/~djb/docs/smtplf.html)

Here is the code, in part, we use to generate the email being sent:
my $_random_boundary = "NextPart_"; my @nums = ( 0 .. 9 ); my @chars = ( "A" .. "Z", "a" .. "z", 0 .. 9, qw() ); $_random_boundary .= join("", @nums[ map { rand @nums } ( 1 .. 3 ) ]); $_random_boundary .= "_" . join("", @nums[ map { rand @nums } ( 1 .. 4 + ) ]); $_random_boundary .= "_" . join("", @chars[ map { rand @chars } ( 1 .. + 8 ) ]); $_random_boundary .= '.' . join("", @chars[ map { rand @chars } ( 1 .. + 8 ) ]); my $__content_type = qq~multipart/alternative; boundary="----=$_random_boundary"~; my %mail = ( "To" => "$__to", "Subject" => "$__subject", "Content-Type" => $__content_type, ); my $_mail_Message = q~ This is a multi-part message in MIME format. ------=~ . $_random_boundary . q~ Content-Type: text/plain; charset="US-ASCII" Content-Transfer-Encoding: 7bit ~ . $__text_message . q~ ------=~ . $_random_boundary . q~ Content-Type: text/html; charset="US-ASCII" Content-Transfer-Encoding: quoted-printable <html> <body> ~ . $__html_message . q~ </body> </html> ------=~ . $_random_boundary . q~-- ~;
That is some of the code, the main parts that the email uses...

My question is this... Is there a subroutine I can pass $_mail_Message to that will get rid of the bare LF and convert the bare LF into CR LF?

thx,
Richard

Replies are listed 'Best First'.
Re: problem with 'bare LF' in script
by graff (Chancellor) on Nov 12, 2008 at 02:12 UTC
    Since you are using a hash (%mail) to set the essential fields for the message header, I assume you are using one of the typical CPAN modules to actually submit the message to an outgoing mail server. Which module are you using?

    If the man page for that module doesn't say anything about line terminations, you might (just for grins) try adding "\r" to the end of each of the header values (as well as doing the  s/\n/\r\n/g thing on the message body) to see what happens.

      Yes, I am using Mail::Sendmail and have been for quite a few years.

      I have tried everything, including these things:
      $__to =~ s/(\r\n|\n\r|\r|\n)/\r\n/sg; $__cc =~ s/(\r\n|\n\r|\r|\n)/\r\n/sg; $__bcc =~ s/(\r\n|\n\r|\r|\n)/\r\n/sg; $__from =~ s/(\r\n|\n\r|\r|\n)/\r\n/sg; $__subject =~ s/(\r\n|\n\r|\r|\n)/\r\n/sg; $__html_message =~ s/(\r\n|\n\r|\r|\n)/\r\n/sg; $__text_message =~ s/(\r\n|\n\r|\r|\n)/\r\n/sg; $__importance =~ s/(\r\n|\n\r|\r|\n)/\r\n/sg; $__xpriority =~ s/(\r\n|\n\r|\r|\n)/\r\n/sg; $__x_ms_priority =~ s/(\r\n|\n\r|\r|\n)/\r\n/sg; $_mail_Message =~ s/(\r\n|\n\r|\r|\n)/\r\n/sg; # And this: $_mail_Message =~ s/\cJ\cM$/\r\n/eg; # Done this for each of the variables...
      Still it does not work. I am thinking at this point, that it is the module, Mail::Sendmail, maybe it is doing something that is causing the errors. I have tried everything, even sending fake information with only one letter in each field and still we get that message.

      Maybe it is time for me to find another module to send out the emails one at a time or a bunch at once.

      thx,
      Richard
        You said:

        I have tried everything, including these things:
        $__to =~ s/(\r\n|\n\r|\r|\n)/\r\n/sg; $__cc =~ s/(\r\n|\n\r|\r|\n)/\r\n/sg; ...

        Um, 'scuse me, but in your OP code snippets, you had this:

        my %mail = ( "To" => "$__to", "Subject" => "$__subject", "Content-Type" => $__content_type, );
        And you didn't really show us where the values of those scalars are coming from. Which means that these hash elements might never have had any line termination characters of any kind (in which case your substitutions would do nothing at all), or if they did have CR and/or LF, you might be screwing things up by having any sort of line-termination characters at all in those header values (this seems more likely).

        You might want to try this (if you haven't already):

        for ( $__to, $__subject, $__content_type, ... ) { tr/\r\n/ /; s/\s+$//; } my %mail = ( "To" => $__to, "Subject" => $__subject, "Content-Type" => $__content_type, );
        That will tell you whether Mail::Sendmail does the right thing in terms of appending CRLF at the end of every header field. If those strings already have CR and/or LF in them, you are probably asking for trouble. Ideally, Mail::Sendmail would be smart enough to make sure that any header field value does not contain either CR or LF before the module itself appends CRLF to each header field for output. (Having spurious CR and/or LF scattered around in the header fields is a Bad Thing.)

        As for the message body, I'd be inclined to try something like this:

        my @message_lines = ( '', # blank line 'This is a multi-part message in MIME format.', '','', # a couple blank lines "------=$_random_boundary", ..., # i.e. one array element for every line of message content '','' # including a couple blanks at the end ); my $_mail_message = join( "\r\n", @message_lines );

        My apologies for giving bad advice earlier (adding "\r" to the header fields) -- I should have known better.

        Interestingly, Mail::Sendmail seems to be doing it right, i.e. it declares my $CRLF = "\015\012";, and then uses this consistently as the line ending whenever needed. In other words, I suppose the problem lies elsewhere.

        $__to =~ s/(\r\n|\n\r|\r|\n)/\r\n/sg; $__cc =~ s/(\r\n|\n\r|\r|\n)/\r\n/sg; $__bcc =~ s/(\r\n|\n\r|\r|\n)/\r\n/sg; $__from =~ s/(\r\n|\n\r|\r|\n)/\r\n/sg; $__subject =~ s/(\r\n|\n\r|\r|\n)/\r\n/sg; $__html_message =~ s/(\r\n|\n\r|\r|\n)/\r\n/sg; $__text_message =~ s/(\r\n|\n\r|\r|\n)/\r\n/sg; $__importance =~ s/(\r\n|\n\r|\r|\n)/\r\n/sg; $__xpriority =~ s/(\r\n|\n\r|\r|\n)/\r\n/sg; $__x_ms_priority =~ s/(\r\n|\n\r|\r|\n)/\r\n/sg; $_mail_Message =~ s/(\r\n|\n\r|\r|\n)/\r\n/sg;

        I personally believe that if those substitutions are in fact all the same substitution, which seems to be the case -and would be most reasonable/probable- although I'm not sure due the alignment... then I should point out, on a totally OT basis wrt your actual problem, that you'd probably better do:

        s{ \n\r | \r | \n }{\r\n}gx for $__to, $__cc, $__bcc, $__from, $__subject, $__html_message, $__text_message, $__importance, $__xpriority, $__x_ms_priority, $_mail_Message;

        I also edited the regex to the point of:

        • removing a set of unnecessary capturing parens;
        • removing a pattern that would be replaced by itself;
        • improving readability with /x (incidentally, /s did nothing there...) and alternate delimiters.
        --
        If you can't understand the incipit, then please check the IPB Campaign.
Re: problem with 'bare LF' in script
by almut (Canon) on Nov 12, 2008 at 00:32 UTC

    Presumably, replacing LF with CR LF in the message body only isn't sufficient. I guess you still have bare LFs in the header section, which - as I understand it - isn't allowed either.

Re: problem with 'bare LF' in script
by GrandFather (Saint) on Nov 11, 2008 at 23:49 UTC

    You could: $_main_Message =~ s/(?<!\0x0d)\x0a(?!\0x0d)/\x0d\x0a/g;.


    Perl reduces RSI - it saves typing
      Thank you, Grandfather, but that did not work...

      Still trying solutions if you know of anything else, I'd appreciate it.

      thx,
      Richard
        No idea if this will help:
        $str =~ s/(\r\n|\n\r|\r|\n)/\r\n/sg;
        where \r is a carriage-return and \n is a line-feed. This code will convert every type of line ending to a CR-LF pair.

        Update: removed parenthesis from replacement text

Re: problem with 'bare LF' in script
by powerhouse (Friar) on Nov 12, 2008 at 07:50 UTC
    I just found this module: Mail::Bulkmail::Dynamic

    Anyone have any experience with it? I read over the information on it at cpan, and it looks like what we can use, since one of our companies has nearly 40,000 members that we email monthly, and another has about 1/4 of that and is going to be larger that by the middle of next year. So we can really use something as efficient as this.

    If you know of one, is there an even better solution?

    thx,
    Richard
      If you know of one, is there an even better solution?
      Outsource :)
Re: problem with 'bare LF' in script
by powerhouse (Friar) on Nov 13, 2008 at 02:20 UTC
    Is there a way to send the mail through another server? We have a database server connected direction via private lan line to this main web server... we are thinking of just trying to port the email to the other server so we can send the email from there instead of from the webserver serving up the webpages...

    I heard it can be done, but have no idea where to find documentation on it... I would really appreciate any pointers about this.

    thx,
    Richard

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://723023]
Approved by GrandFather
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others exploiting the Monastery: (5)
As of 2024-04-20 02:28 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found