Wanted to know if there are any functions/classes/etc.. to help with the 990 character limitation for email as my HTML is being effected due to this.
The Problem: (Source)
Note that mailservers have a
990-character limit on each line
contained within an email message. If
an email message is sent that contains
lines longer than 990-characters,
those lines will be subdivided by
additional line ending characters,
which can cause corruption in the
email message, particularly for HTML
content. To prevent this from
occurring, add your own line-ending
characters at appropriate locations
within the email message to ensure
that no lines are longer than 990
characters.
Anyone else seem to have this problem? and how did you fix this?
Sounds like I need to find a good place to split my HTML and manually add a line break, ugh...
UPDATE:
It's tablature data with many rows. So do I need to add a \n or <br /> somewhere?
UPDATE #2: Adding MIME Type Code
$headers = "MIME-Version: 1.0" . "\r\n";
$headers .= "Content-type:text/html;charset=iso-8859-1\r\n";
$headers .= "Content-Transfer-Encoding: quoted-printable\r\n"; // added this, but still no results
$headers .= "From: from#email.com\r\n";
Here is how I'm calling the function(s):
How I originally called:
return $html;
What I tried:
return imap_8bit($html); // not working, nothing is captured in the error log
AND
return imap_binary($html); // not working, nothing is captured in the error log
UPDATE #3 (Adding Mail Function)
try {
mail(
'to#email.com',
'Subject of Email',
$html,
$headers
);
} catch (Exception $e) {
echo ("ERROR: Email NOT sent, Exception: ".$e->getMessage());
}
Example HTML (This is the message of the HTML email) (This is also in a class that is part of a XMLRPC service)
private function getHTML() {
$html = '<html><head><title>Title</title></head><body>';
$html .= '<table>';
$html .= '<tr><td>many many rows like this</td></tr>';
$html .= '<tr><td>many many rows like this</td></tr>';
$html .= '<tr><td>many many rows like this</td></tr>';
$html .= '<tr><td>many many rows like this</td></tr>';
$html .= '<tr><td>many many rows like this</td></tr>';
$html .= '</table>';
$html .= '</body>';
$html .= '</html>';
return $html;
//return imap_8bit($html); // not working, nothing is captured in the error log
//return imap_binary($html); // not working, nothing is captured in the error log
// Both of these return the XMLRPC Fault Exception: 651 Failed to parse response
}
Fault Exception: 651 Failed to parse response basically doesn't like the format or how the data is returned.
You can put your content through the wordwrap() function so that you don't manually have to insert newlines.
Have you considered using one of the many mail libraries available? PHPMailer, PEAR Mail, SwiftMailer, etc...?
Order servers have an even lower limit: 76 chars per line + \r\n.
You have to make use of the imap_8bit() and imap_binary() functions in order to convert your data to a base64 or quoted-printable encoding.
You can also use an existing library, like SwiftMailer.
Actually, this is not a "mail server" problem. The SMTP line limit dictates the number of characters allowed on each line during transmission. The SMTP RFC allows for up to 1000 characters per line, and default postfix installed cap at 998 characters. You should contact your hosting provider on increasing your SMTP line limit if you feel it's necessary to exceed the RFC.
Related
I am trying the below code to send encrypted mail where the cleartext is text/html and charset is utf-8.
For what it's worth, I cannot manage to get the mail displayed correctly (in MS Outlook).
As you may notice, I (meanwhile) try to have the relevant Content-Type: header both prepended to the data file to be encrypted and present in the headers parameter of the call to openssl_pkcs7_encrypt (and tried various other combinations as well).
While the desired content-type applies to the message when it is sent unencrypted, it simply does not work with encrypted messages. The result is always as if the "inner" Content-Type had been text/plain;charset=ascii.
I experimented with prepending the header to the data file before encryption only because I think I found some suggestion similar here on SE for a similar situation. But apparently this only makes the header line appear as part of the decrypted message (in other words, the file submitted to openssl_pkcs7_encrypt should really only be the "pure" content (as I had orginally suspected).
But having it in the headers parameter does not help, either: In the headers present in the enncryped file, there is a header added with the correct "outer" S/MIME content type, which overrides my "inner" content type given.
Question: Where and how in the combination of openssl_pkcs7_encrypt() and mail() should I specify the "inner" Content-Type of my encrypted message?
$hdr_to = implode(',',$empfaenger);
$hdr_subject = '=?UTF-8?q?' . quoted_printable_encode($subject) . '?=';
$other_headers = array(
"From" => $hdr_from,
"Content-Type" => "text/html; charset=utf-8",
"X-Mailer" => "PHP/".phpversion()
);
$mailbody = wordwrap($_REQUEST['message']);
//write msg to disk
$msg_fn = tempnam("/tmp","MSG");
$enc_fn = tempnam("/tmp","ENC");
$fp = fopen($msg_fn, "w");
fwrite($fp, 'Content-Type: ' . $other_headers['Content-Type'] . CRLF . CRLF);
fwrite($fp, $mailbody);
fclose($fp);
// Encrypt message
$enc_ok = openssl_pkcs7_encrypt($msg_fn,$enc_fn,$pubkeys,$other_headers,PKCS7_TEXT,1);
//$enc_ok = false; // for debugging: simulate encryption failure
if (!$enc_ok) {
// Will try to send unencrypted instead
} else {
// Seperate headers and body for mail()
$data = str_replace("\n",CRLF,file_get_contents($enc_fn));
$parts = explode(CRLF.CRLF, $data, 2);
$mailbody = $parts[1];
$other_headers = $parts[0];
}
// Send mail
$mail_ok = mail($hdr_to, $hdr_subject, $mailbody, $other_headers);
The problem was the PKCS7_TEXT flag given as parameter to the encryption function.
My intended media type was text/html; charset=utf-8, i.e.,
of type text
of subtype html
with parameter charset=utf-8
and superficially, the type matches what the name PKCS7_TEXT suggests. However, this flag is described as:
Adds text/plain content type headers to encrypted/signed message. If decrypting or verifying, it strips those headers from the output - if the decrypted or verified message is not of MIME type text/plain then an error will occur.
To be precise, it seems that said header and a blank line (to separate it from the message body) are prepended, which turns any previously existing header lines (Content-Type: or other) into part of the body.
So the simple solution is to not use the PKCS7_TEXT flag (unless your message is really plain ASCII² text).
² It may also be okay for latin-1 text, but I won't count on it. After all the description quoted above suggests that an error will occur; then again, UTF-8 text gets decrypted successfully (i.e., without an explicit error), but exhibits the usual codepage related display artefacts .
I am using imap_open function in PHP to download emails and insert them into a mysql database
Here is my code to get the headers and body message etc:
$emails = imap_search($inbox,'ALL');
//if emails are returned, cycle through each...
if($emails)
{
//begin output var
$output = '';
//put the newest emails on top
rsort($emails);
//for every email...
foreach($emails as $email_number)
{
//get information specific to this email
$header=imap_headerinfo($inbox,$email_number);
$structure = imap_fetchstructure($inbox,$email_number);
$from = $header->from[0]->mailbox . "#" . $header->from[0]->host;
$toaddress=$header->to[0]->mailbox."#".$header->to[0]->host;
$replyto=$header->reply_to[0]->mailbox."#".$header->reply_to[0]->host;
$datetime=date("Y-m-d H:i:s",$header->udate);
$subject=$header->subject;
$message = quoted_printable_decode(imap_fetchbody($inbox,$email_number,1.1));
if($message == '')
{
$message = quoted_printable_decode(imap_fetchbody($inbox,$email_number,1));
}
}
}
but it doesnt seem to get the body of all emails. For example, when it receives Read Receipts the body is just blank and the same with some other emails people send.
sometimes, the email body looks like:
PGh0bWw+DQo8aGVhZD4NCjxtZXRhIGh0dHAtZXF1aXY9IkNvbnRlbnQtVHlwZSIgY29udGVudD0i dGV4dC9odG1sOyBjaGFyc2V0PXV0Zi04Ij4NCjwvaGVhZD4NCjxib2R5IHN0eWxlPSJ3b3JkLXdy YXA6IGJyZWFrLXdvcmQ7IC13ZWJraXQtbmJzcC1tb2RlOiBzcGFjZTsgLXdlYmtpdC1saW5lLWJy ZWFrOiBhZnRlci13aGl0ZS1zcGFjZTsgY29sb3I6IHJnYigwLCAwLCAwKTsgZm9udC1zaXplOiAx NHB4OyBmb250LWZhbWlseTogQ2FsaWJyaSwgc2Fucy1zZXJpZjsiPg0KPGRpdj4NCjxkaXY+DQo8 ZGl2PnJlcGx5PC9kaXY+DQo8ZGl2Pg0KPHAgc3R5bGU9ImZvbnQtZmFtaWx5OiBDYWxpYnJpOyBt YXJnaW46IDBweCAwcHggMTJweDsiPjxiPktpbmQgUmVnYXJkcyw8YnI+DQo8YnI+DQpDaGFybGll IEZvcmQgfCZuYnNwOzwvYj48c3BhbiBzdHlsZT0iY29sb3I6IHJnYigyNTIsIDc5LCA4KTsiPjxi PlRlY2huaWNhbCBNYW5hZ2VyJm5ic3A7PC9iPjwvc3Bhbj48Yj58Jm5ic3A7SW50ZWdyYSBEaWdp dGFsPC9iPjxmb250IGNvbG9yPSIjNTk1OTU ... continued
How can i convert the whole message body to be plain text
Here's what I use, in general. $email refers to one of the objects from the return of eg imap_fetch_overview:
$structure = imap_fetchstructure($email->msgno);
$body = imap_fetchbody($email->msgno, '1');
if (3 === $structure->encoding) {
$body = imap_base64($body);
} else if (4 === $structure->encoding) {
$body = imap_qprint($body);
}
Note there are 6 possible encodings (ranging from 0 to 5), and I'm only handling 2 of them (3 and 4) -- you might want to handle all of them.
Also note I'm also getting only the 1st part (in imap_fetchbody) -- you might want to loop over the pieces to get them as needed.
Update
One other thing I noticed about your code. You're doing imap_fetchbody($inbox,$email_number,1.1). That third argument should be a string, not a number. Do this instead:
imap_fetchbody($inbox, $email_number, '1.1')
The code given handles only simple text messages having at most one sub-part and no encoding. This is basically the simplest kind of email there is. The world used to be that simple, sadly no more!
To handle more email, your code must be expanded to handle:
Multi-parts
Encodings
Multi-part is the concept that a single email message (a bunch of data) can be divided into multiple, logically-separate pieces. In the simplest case, there is only one part: the text of the message. In the next simplest case, there is message text with a single attachment. The next simplest case is message text plus multiple attachments. Then it starts to get hard, when the text of the message refers inline or embeds the attachments (think of an HTML message with an image -- that image could be an attachment that's linked with "local" CSS or embedded as eg base64 data url).
Encoding is the idea that email needs to accommodate the lowest common denominator of SMTP servers on the Internet. From 1971 to the early 1990s, most email messages were plain text using 7-bit US ASCII character set -- and SMTP mailers in the middle relied on this 7-bit framework. As the need for character sets became more apparent, simultaneously with the need to send binary data (eg images), 8-bit SMTP mailers cropped up as did various methods to shoe-horn 8-bit clean data into 7-bits. These include quoted-printable and base64. While 7-bit is virtually dead, we still have all the hoops of this history to jump through.
Rather than re-invent the wheel, there is a good piece of code on PHP.net that handles multi-part encoded messages. See the comment by david at hundsness dot com. You would use that code like this:
$mailbox = imap_open($service, $username, $password) or die('Cannot open mailbox');
// for all messages
$emails = imap_fetch_overview($mailbox, '1:1'/* . imap_check($mbox)->Nmsgs*/);
foreach ($emails as $email) {
// get the info
getmsg($mailbox, $email->msgno);
// now you have info from this message in these global vars:
// $charset,$htmlmsg,$plainmsg,$attachments
echo $plainmsg; // for example
}
imap_close($mailbox);
(Side note: his code has three parse errors, where he does ". =" to mean ".=". Fix those and you're good to go.)
Also, if you're looking for a good blog on doing this "from the ground up", check out this: http://www.electrictoolbox.com/php-imap-message-parts/
I am using the following script http://stuporglue.org/recieve-e-mail-and-save-attachments-with-a-php-script/ to handle my emails that get sent to me, however it seems if a user sends an email from mail or outlook or any email client that sends base64 attachments they are not being saved in the data base, and the body text of the email is also skiped.
I am wondering if anyone sees an error in the code, as I have looked and dont see anything that sticks out.
a closer look shows the following
Mail.app sends its base64 like this.
--Apple-Mail=_9E76B10A-4086-43B8-B835-78F184FA43FC
Content-Disposition: inline;
filename=CV-IT.pdf
Content-Type: application/pdf;
name="CV-IT.pdf"
Content-Transfer-Encoding: base64
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
1NVM1hk3kE1G3rlPZKL2CeZ+Hdp
while Gmail sends it like this.
Content-Type: application/pdf; name="CV-IT.pdf"
Content-Disposition: attachment; filename="CV-IT.pdf"
Content-Transfer-Encoding: base64
X-Attachment-Id: f_gx86pbon0
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
1NVM1hk3kE1G3rlPZKL2CeZ+Hdp
The gmail attachment saves while the mail.app does not.
disclaimer the problematic script in question has more issues, which I will not address, and the answer below is meant as a quick fix for the problem at hand, while hoping to enlighten some readers who were not able to diagnose the problems themselves. /disclaimer
There are two main problems.
Problem 1: split header lines
Look at these headers:
Content-Disposition: inline;
filename=CV-IT.pdf
Content-Type: application/pdf;
name="CV-IT.pdf"
versus
Content-Type: application/pdf; name="CV-IT.pdf"
Content-Disposition: attachment; filename="CV-IT.pdf"
Now look at the part that processes these lines:
$info = split("\n",$parts[0]);
..
foreach($info as $line)
{
if( preg_match("/Content-Type: (.*);/",$line,$matches) )
{
$type = $matches[1];
}
if( preg_match("/Content-Disposition: attachment; filename=\"(.*)\"/",
$line,$matches) ) {
$name = time() . "_" . $matches[1];
}
..
}
This splits the header in lines, and then tries to match every line. Now look at the two headers. The second (working) one has 2 lines, which are perfectly matched.
The first (not working) one has 4 (!) lines. None of these 4 lines matches the patterns.
There are countless ways of tackling this problem, and I'll take a quick&dirty oneliner. Add this line before $info = split("\n",$parts[0]);
$parts[0] = preg_replace("/\r?\n\s+/"," ",$parts[0]);
it will turn the split headers into oneliners again by looking for newlines followed by whitespace, and replacing them with just one space.
Problem 2: wrong pattern
Assuming you applied the fix above, you have this pattern:
if( preg_match("/Content-Disposition: attachment; filename=\"(.*)\"/", ...
trying to match this line:
Content-Disposition: inline; filename=CV-IT.pdf
Two things go wrong here:
problem 2a: disposition inline/attachment
The pattern clearly looks for the word "attachment", while the line says "inline". This is fixed by replacing attachment by (attachment|inline), which indicates an alternative. (note that this also captures the disposition type)
problem 2b: filename double quotes
The pattern further looks for filename="(.*)", while the line has a filename without the quotes.
This is also no major issue, if you insert ? after the ", to indicate that the " is optional, all will work. To make it perfect, you must also ensure that the . will not match the ending " if available, so replace filename="(.*)" with:
filename="?([^"]+)"?
where [^"]+ stands for 'anything but "'.
So if you change these lines:
if( preg_match("/Content-Disposition: attachment; filename=\"(.*)\"/",
$line,$matches) ) {
$name = time() . "_" . $matches[1];
}
into
if( preg_match('/Content-Disposition: (attachment|inline); filename="?([^"]*)"?/',
$line,$matches) ) {
$disposition = $matches[1];
$name = time() . "_" . $matches[2];
}
it should work. (note that I changed the pattern to use single quotes, so that you need not escape the double quotes, making things legible)
To make this script fool proof, you should really read the appropriate RFCs, to see what more is to be expected in email headers. This script has a lot of assumptions buried in it.
The problem is that my script is not looking for inline content, only for attached content. With the way you have attached the file, it is inline, hence the
Content-Disposition: inline;
filename=CV-IT.pdf
If you attach it, you would instead see
Content-Disposition: attachment; filename="CV-IT.pdf"
The Content-Disposition handling is around line 54-64 of the script on my site (linked in original question).
seems you used preg_match to get the boundary of the mail near line 166:
if (preg_match("/boundary=(.*boundary)$/",$line,$matches)){
$boundary = $matches[1];
You used the "/" character as delimiter of pattern of regular expression and you have the "/" in your boundary content at the same time.
So this may be the reason why your code does not work.
Try this:
if (preg_match("{boundary=(.*boundary)$}",$line,$matches)){
$boundary = $matches[1];
When creating a script to send emails using the PHP mail() function I'm coming across issues with new lines. PHP on Unix systems expect headers to be separated with a LF character, despite what the docs say, sendmail then replaces these with the correct CRLF. However on Windows the message and headers are sent as provided. This was described in a long running PHP bug report.
So I need a method of detecting whether the system is running the Unix version of sendmail in order to use LF and use CRLF on Windows. I'm aware of PHP_EOL but I'm wondering if there's a more elegant way of handling this.
Currently I'm building my message, as specified by the docs, like so.
<?php
$to = "example#website.com";
$subject = "Email Subject Here";
$message = "Hello this is a plaintext\n message with a line break.";
$headers = array(
"From: webmaster#example.com",
"Reply-To: webmaster#example.com",
"X-Mailer: PHP/" . phpversion()
);
$success = mail($to, $subject, $message, join("\r\n", $headers));
if ($success) {
echo "Mail Sent\n";
} else {
echo "Mail Failed\n";
}
On Unix systems this results in the following message being sent to sendmail (\r and \n have been replaced by textual representations):
To: example#website.comLF
Subject: Email Subject HereLF
X-PHP-Originating-Script: 501:mail.phpLF
From: webmaster#example.comCRLF
Reply-To: webmaster#example.comCRLF
X-Mailer: PHP/5.3.1LF
LF
Hello this is a plaintextLF
message with a line break.LF
When this is passed to sendmail all LF are replaced with CRLF resulting in duplicate carriage returns. Some mail servers then replace this additional CR with CRLF resulting in an additional line break and all headers, in this case after From:, are now part of the message body.
PHP actually inserts the X-PHP-Originating-Script header with incorrect line ending, which is a side issue but still annoying. – Actually a PHP 5.3 bug, now fixed.
Any ideas on an ideal way of handling this cross platform?
Thanks,
Aron
This was a rather transient defect in the early 5.3 releases see this bug notice
Upgrade your PHP
I have a small php mailer script within a php file that works fine and sends mail fine:
$subject = "subject";
$mail_body = "mail body";
$name = "noreply";
$email = "noreply#domain.com";
$recipient = "somebody#domain.com";
$header = "From: ". $name . " <" . $email . ">\r\n";
mail($recipient, $subject, $mail_body, $header);
However, if I take this out and make it its own file, or put it into a different file, it doesn't work. There are no error messages and email is not sent.
There are no php ini set commands and no included php files.
Any ideas on why it works in the larger php script, but doesn't work on its own?
Everything is OK with your code. I tested it by only replacing the email address in $recipient with my address and it worked fine (I tested it with my corporate email - Outlook on Exchange server and another test with an Hotmail address - both worked fine and reached my inbox).
But make sure that new lines in $mail_body are "\n" and not "\r\n". As you can read in the docs about the message parameter:
Each line should be separated with a
LF (\n). Lines should not be larger
than 70 characters.
Make sure $name and $email does not contain forbidden characters like <, >, and new lines (\r, \n, or \r\n). As Michael points out new lines in there can lead to email injection attacks. You don't want your contact form to be used as a mail platform by spammers!
You should consider using an email library like PHPMailer which will ease your development since mail() is quite tricky for advanced mailing. Most of these libraries already cover these attacks and standards...