View Full Version : No Line Breaks in Email Using Perl and sendmail
blitzen
06-13-2005, 12:38 AM
Hi,
I have a script that I loaded on another hosting company.
I just moved it to Futurequest server. The old server (LINUX) had no problems.
On FutureQuest, the email that I receive no longer has the line breaks. All text is strung out in one line.
I tried using "\n" in the message body and it does not work.
(Neither does "<br>" - that is because the email is sent as ascii, not html email.)
I am befuddled as to why the email that I receive that is dispatched from FutureQuest is strung out in one line.. Can anyone out there help me resolve this?
Thank you.
Joseph
06-13-2005, 12:39 AM
You will need to post the code you are using, so we can see how you are sending the email. :smile:
blitzen
06-13-2005, 10:27 AM
Thank you for your quick response.
The input is received from an html form. Here is one part of the code. It prepares the email output. Look for the template called "newmessage". The templates are simple html snippets with parameters obtained from the program.
sub usernotify {
my $cfg = $_[0]->{cfg};
my $ticket = $_[0]->{ticket};
my $email = $ticket->{'email'};
my $name = $ticket->{'name'};
my %macros;
$name = 'Customer' if $name eq undef;
my $subject;
my $messages = $ticket->{messages};
my $tmpl;
if (@{$messages} == 1) {
$tmpl = 'newticket';
if ($cfg->get('validate') ne undef) {
$tmpl .= 'validate';
$macros{ENV_HTTP_HOST} = $ENV{HTTP_HOST};
$macros{VALIDATIONCODE} = $_[0]->{validationcode};
}
} else {
$tmpl = 'newmessage';
}
if (open(TMPL, $cfg->get('basedir')."/templates/$tmpl.txt")) {
my @buff = <TMPL>;
close TMPL;
$tmpl = join('', @buff);
}
$macros{TICKETID} = $ticket->{id};
$macros{TICKETSTATE} = TTXCommon::status($ticket->{status});
$macros{UNAME} = $name;
$macros{COMPANYNAME} = $cfg->get('company');
$macros{UEMAIL} = $email;
$macros{TICKETURL} = "http://$ENV{HTTP_HOST}$ENV{SCRIPT_NAME}?cmd=ticket&key=".$ticket->{key}.
"\n\nACCESS KEY: ".$ticket->{key};
my $msg = $messages->[@{$messages} - 1];
my @msgparts = split(/\n\n/, $msg);
shift @msgparts;
my $body = join("\n\n", @msgparts);
$body =~s/\[b]//g;
$body =~s/:\[\/b]/:/g;
##If I add the following statement, the email still does not have linebreaks. It will, instead, have a space where the \n's are.
# $body .= "\nTHIS IS MY ATTEMPT AT A LINE BREAK.\n";
###This part prepares the customer email.
$macros{MESSAGE} = $body;
for (my $i = 0; $i < 9; ++$i) { $macros{"C$i"} = $ticket->{"c$i"}; }
$tmpl =~ s/\(%\s*([A-Z0-9_]+)\s*%\)/$macros{$1}/g;
$subject = "Ticket ".$ticket->{id};
$subject .= ", ".$ticket->{subject} if $ticket->{subject} ne undef;
TTXMail::sendmail(
{
to => $email,
from => "\"".$cfg->get('company')."\" <".$cfg->get('email').">",
# from => "\"".$cfg->get('company')."\" <" . (($cfg->get('_USER') ne undef && $cfg->get('_USER')->{email} ne undef)? $cfg->get('_USER')->{email}:$cfg->get('email')) . ">",
subject => $subject,
msg => $tmpl
}
);
if ($cfg->get('emaillist') ne undef) {
my $n = $cfg->get('emaillist');
if ($n =~ /^\d$/) {
my @addrlist = split(/,/, $ticket->{"c$n"});
foreach my $addr (@addrlist) {
$addr =~ s/\s//g;
TTXMail::sendmail(
{
to => $addr,
from => "\"".$cfg->get('company')."\" <".$cfg->get('email').">",
subject => $subject,
msg => $tmpl
}
);
}
}
}
}
Here is the TTXMail::sendmail routine that actually sends the email via the sendmail, not smtp.
sub sendmail {
my $cfg = TTXData::get('CONFIG');
$doemailfix = $cfg->get('emailfix');
if ($cfg->get('broadcast') ne undef) {
$_[0]->{bcc} = $cfg->get('broadcast');
}
$mailer = $cfg->get('mailer');
$smtphost = $cfg->get('smtp');
my $msg = $_[0]->{msg};
$msg = TTXMarkup::strip($msg);
my $contenttype = "MIME-Version: 1.0\nContent-Type: text/plain; charset=\"ISO-8859-1\"\nContent-Transfer-Encoding: quoted-printable";
if (!smtp()) {
return 0 if !open(MAIL, "|$mailer -t");
my $bcc = "Bcc: ".$_[0]->{bcc}."\n" if $_[0]->{bcc} ne undef;
print MAIL "To: ".$_[0]->{to}."\nFrom: ".encode($_[0]->{from}, 1)."\n".$bcc.
"Subject: ".encode($_[0]->{subject}, 0).
"\n$contenttype\n\n".
quoteit($msg)."\n\n";
close MAIL;
} else {
my $to = $_[0]->{to};
$to =~ s/"[^"]*"//;
$to =~ s/^[^<]*<//g;
$to =~ s/>[^>]*$//g;
$to =~ s/^\s+//;
$to =~ s/\s+$//;
my $from = $_[0]->{from};
$from =~ s/"[^"]*"//;
$from =~ s/^[^<]*<//g;
$from =~ s/>[^>]*$//g;
$from =~ s/^\s+//;
$from =~ s/\s+$//;
if ($cfg->get('smtptrace')) {
# save original STDERR destination
open SAVERR, ">&STDERR";
# redirect STDERR handle to a file
open STDERR, '>>'.$cfg->get('basedir').'/smtptrace.txt';
my $oldfh = select STDERR; $| = 1; select($oldfh); # make unbuffered
}
my $s = Net::SMTP->new($smtphost, Debug => $cfg->get('smtptrace') ? 1:0);
if ($s ne undef) {
if ($cfg->get('smtplogin') ne undef && $s->can('auth')) {
eval "\$s->auth(\$cfg->get('smtplogin'), \$cfg->get('smtppwd'));";
if ($@ ne undef) {
if ($cfg->get('smtptrace')) {
warn $@;
warn 'Trying Net::POP3';
}
eval "use Net::POP3;";
if ($@ ne undef) {
if ($cfg->get('smtptrace')) {
warn $@;
}
} else {
my $pop = Net::POP3->new($smtphost);
if (!$pop) { warn "Can't open connection to pop3 server: $!"; }
elsif (!defined ($pop->login($cfg->get('smtplogin'), $cfg->get('smtppwd')))) {
warn "Can't authenticate: $!";
} else {
my $messages = $pop->list();
$pop->quit();
}
}
}
}
$s->mail($from);
if ($_[0]->{bcc} ne undef) {
$s->to($to, $_[0]->{bcc});
} else {
$s->to($to);
}
$s->data();
$s->datasend("To: ".$_[0]->{to}."\n");
$s->datasend("From: ".encode($_[0]->{from}, 1)."\n");
$s->datasend("Subject: ".encode($_[0]->{subject}, 0).
"\n$contenttype\n\n");
$s->datasend(quoteit($msg));
$s->datasend("\n\n");
$s->dataend();
$s->quit();
if ($cfg->get('smtptrace')) {
# restore original STDERR destination
open STDERR, ">&SAVERR";
}
}
}
return 1;
}
kitchin
06-13-2005, 12:44 PM
My guess: the template line endings got botched up in the transfer to the new host. Like, the file extension is not listed as text in your FTP prgram or something.
Otherwise... for debugging, I would start adding those
. "\nTHIS IS MY ATTEMPT AT A LINE BREAK.\n";
strings at the other end, at the mail sending line, and work upwards. So:
quoteit($msg). "\nTHIS IS MY ATTEMPT AT A LINE BREAK, at: .\n" . __LINE__;
... if I remember how __LINE__ works.
Bruce
06-13-2005, 07:34 PM
I notice in TTXMail::sendmail that the entire body of the message gets wrapped by a "quoteit" function. What does this function do?
REMIYA
06-13-2005, 08:42 PM
On some servers depending on the OS, you may have to use \r\n instead of only \n.
Give it a try.
Hope that helps :)
Bruce
06-14-2005, 12:09 AM
On some servers depending on the OS, you may have to use \r\n instead of only \n.While the SMTP protocol requires carriage-return (\r) plus line-feed (\n) to end lines, all UNIX mail server software that I am aware of (including qmail, which we use) uses just plain line-feed internally, both for storage of email and for submitting new messages.
CDarklock
06-14-2005, 01:04 PM
I notice in TTXMail::sendmail that the entire body of the message gets wrapped by a "quoteit" function. What does this function do?
While I'm not familiar with TTXMail specifically, it probably sticks the ">" before the word "From" and doubles the "." character, when these occur at the beginning of the line.
This is done because when the SMTP protocol was authored, there was software in widespread use with problematic bugs related to these two situations. So now, thirty years later, we still work around those bugs even though the software which had them is long gone.
The moral of the story is "fix the bugs, not the protocol".
blitzen
06-14-2005, 01:43 PM
I notice in TTXMail::sendmail that the entire body of the message gets wrapped by a "quoteit" function. What does this function do?
I remove the quoteit and it now works fine.
I don't know what quoteit does, but removing it worked. Thank you for the keen eyesight.
----------- Case Closed -----------
vBulletin® v3.6.8, Copyright ©2000-2009, Jelsoft Enterprises Ltd.