CodeIgniter SMTP email message - characters replaced with equal signs - php

I'm using the CodeIgniter email library to send emails using our Exchange server. The problem I get is that the content of the email gets messed up.
There are some words that get replaced with equal signs "=", I tried 2 different Exchange servers (they are in different locations and have no relation what so ever) and I still get the same issue. If I use any other server as an SMTP server to send emails everything works fine and the content stays intact and unchanged.
Content before sending:
Dear Customer
Please find attached a comprehensive explanation of how to get our brochure of Angola. This has been sent to you at the request of Alex.
The information has been taken from www.example.co.uk "Company name" is one of the leading tile and marble companies in the UK.
Content after sending it through the Microsoft Exchange:
Dear Customer
Please find attached a comprehensive explanation of how to get our brochure of A=gola. This has been sent to you at the request of Alex.
The information has been taken from www.example.co.uk "Company name" is one of the leadi=g tile and marble companies in the UK.
As you can see for some reason some of the "n" characters were replaced with equal signs "=" (Example: Angola > A=gola)
My email configuration:
$this->load->library('email');
$config['charset'] = 'utf-8';
$config['mailtype'] = 'html';
// SMTP
$config['protocol'] = 'smtp';
$config['smtp_host'] = 'exchange.example.com'; //ssl://
$config['smtp_user'] = 'email#example.com';
$config['smtp_pass'] = 'password';
$config['smtp_port'] = 25;
$this->email->set_newline( "\r\n" );
$this->email->initialize( $config );
$this->email->clear();
......
$this->email->from( $frome, $fromn );
$this->email->to( $email );
$this->email->subject( $subject );
$this->email->message( $send_message );
$this->email->send();
Does anyone know why is the Microsoft exchange behaving this way? or is there some sort of setting I should use?

That's odd, specially since not all the ns are transliterated and not at a specific position.
Try calling $this->email->set_crlf( "\r\n" ); as well. Look up the message details in Exchange and inspect the Content-Type and Charset / Encoding - post the raw thing here so we can inspect it.
I found this in Microsoft Knowledgebase:
Microsoft Exchange uses an enhanced character set. The default MIME
character set for Microsoft Exchange is ISO 8859-1. Some gateways do
not support the way this character set issues a soft return for line
feeds. When this occurs, each line is terminated with an equal sign
showing the line break where the gateway's line-length support ends.

I solved this (kinda) by setting $charlim = '998' in the _prep_quoted_printable function.
When I set $crlf = "\r\n" the resulting email was completely garbled for some reason. But I noticed that the = signs were appearing at regular intervals which was caused by the line length being limited to 76 characters. So increasing the max characters per line (998 is the RFC2822 limit) solves the problem, as long as you don't have really long lines.

Related

Charset of attachment file name

Good Day,
I'm sending an email with an attachement via SMTP with PHPMailer.
The charset in the mail is set to utf-8, but when I send an attachement with an special char like 'März' for example, the client gets an attachement with an broken charset like: M�rz.
My Code Example:
$mail = new PHPMailer();
$mail->IsSMTP();
$mail->CharSet = 'UTF-8';
$mail->Host = "host ip";
$mail->SMTPDebug = 0;
$mail->SMTPAuth = true;
$mail->Port = 25;
$mail->Username = "user";
$mail->Password = "pw";
$mail->setFrom('send#host.de', 'Host');
$mail->addAddress("client#mail.de");
$mail->Subject = 'Subject';
$mail->Body = "Email Content";
$mail->AltBody = 'Alternative Email Content';
$mail->AddAttachment("example/file_märz.pdf");
Am I doing something wrong or is there any fix for this problem?
Looking at the PHPMailer in the attachment process i found basename
was used. So to correctly output the specific encoding you need to setlocale depending on what charset compatible to your filename.
setlocale(LC_ALL, 'ja_JP.UTF-8');
the above code worked for me. Since I am using Japanese language/text for my filename.
If the problem is with the filename, and you're writing the file name inside the source code of your application (in the PHP file), then the problem can be one or both of the following:
The PHP file is saved with the wrong encoding. That is, you're telling PHPMailer to send UTF-8 emails, but your PHP file could be saved in ISO-8859-1 encoding. Thus, when PHP reads the "example/file_märz.pdf", it reads the byte sequence in ISO-8859-1, but then it tells PHPMailer to interpret it as UTF-8.
Solution: ensure your text editor is saving files in UTF-8
The operating system and/or client does not support Unicode file names for attachment.
Solution: there isn't really a solution, you need to avoid non-ASCII characters in file names (which couldn't be a bad idea anyways).
If your editor is already set to UTF-8 and you are sure your client/OS support Unicode in filenames, you need to check the raw email that PHPMailer sends and see what it contains. Many email clients let you see the raw email (the entire raw text).
Blockquote
I had the same problem.
It can be solve by adding:
utf8_encode() function to the $name of the attachment[] array.
On my version of phpmailer is located on class.phpmailer.php on line 1322.

PHP: How to distinguish between encrypted and unencrypted email?

I want to create a new email account which only receives encrypted email. Unfortunately, I cannot modify the mail server configuration so I considered checking incoming email every 2 minutes with a cronjob and automatically rejecting those messages which are not encrypted.
So far I did this:
$body = imap_body($mbox, $i);
if (substr($body,0,27) == "-----BEGIN PGP MESSAGE-----")
$encrypted = true;
else
$encrypted = false;
Works, but I'm pretty sure I don't capture all encrypted email. I didn't find a unique option in the header which would tell me that a message is encrypted. Enigmail left a message though:
X-Enigmail-Version: 1.5.1
This, however, does not help me in any way. Is it enough to just grep for the BEGIN PGP MESSAGE string as I did above?
As a student of computational linguistics my first idea was to try it statistically:
As far as I know encrypted messages do not contain spaces. So you could tokenize the email body into words, and calculate the average length of the words. Try this on some other mails or texts and see how the average length differs.
It may be a bit extravagant, but is more effective than looking for a substring: for example someone may send a webpage or text dealing with encryption or the latest NSA leaks ;-)

imap_open function in PHP sometimes see blank message body

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/

MIME header appering in message body with PHP Mailer

I've been trying out the PHPMailer sample script as given in its README file. Now, when I run that script:
<?php
require("phpmailer.inc.php");
$mail = new phpmailer;
//$mail->IsSMTP(); // set mailer to use SMTP
$mail->From = "from#email.com";
$mail->FromName = "Mailer";
//$mail->Host = "smtp1.site.com;smtp2.site.com"; // specify main and backup server
$mail->AddAddress("someone#someplace.com");
//$mail->AddAddress("ellen#site.com"); // name is optional
$mail->AddReplyTo("info#site.com", "Information");
$mail->WordWrap = 50; // set word wrap
//$mail->AddAttachment("c:\\temp\\js-bak.sql"); // add attachments
//$mail->AddAttachment("c:/temp/11-10-00.zip");
$mail->IsHTML(true); // set email format to HTML
$mail->Subject = "Here is the subject";
$mail->Body = "This is the message body";
$mail->Send(); // send message
?>
I get the following warning :
Warning: mb_send_mail() [function.mb-send-mail]: Unsupported charset
""iso-8859-1";" - will be regarded as ascii in
/export/opt/samplefiles/phpmailer.inc.php on line 162
and the message that is received contains the header as well:
Mime-Version: 1.0 This is the message body
Please help
That first warning hints at mb_send_mail() being used over the ordinary mail() function. Which is unlikely to be prepared for in the PHPMailer package.
It's the setting mbstring.func_overload you have to watch out for. It shouldn't have bit zero set. (For example change 5 to 4 -- or from seven to six,-- or for example from 3 to 2.)
It has to be set in the php.ini or .user.ini. Function overloading can't be fixed at runtime.
If that's not adaptable then a workaround might be mb_internal_encoding("UTF-8"); to eschew the error message, after applying mb_encode_mimeheader() on supplied values. Likely you have to adapt PHPMailer to omit the quotes around charaset parameters however.
I just realized that I've actually been using an older version of PHPMailer (version 0.89 or something). I've gotten myself a newer 5.2 and it appears resolved. Thanks anyway :P

Danish characters with Easy APNs

I am trying to send Danish characters (Æ, Ø, Å) in an alarm notification using Easy APNs but when doing so, no message is send. If I send it with sound, only the sound is send. Also the message will be set to "null" in the database if it includes any of the Danish characters.
Does anyone know a fix for this?
This was caused by json_encode(). Using utf8_encode() on my alert views before json_encode() solved the issue.
UPDATE (How to fix the issue)
1. In class_APNS.php around line 411, you have
$msg = chr(0).pack("n",32).pack('H*',$token).pack("n",strlen($message)).$message;
Above that, put:
$message = utf8_encode($message);
2. In class_APNS.php (same file) put this:
$usermessage['aps']['alert'] = utf8_encode($usermessage['aps']['alert']);
Put it just above the following:
$fk_device = $this->db->prepare($list[$i]);
$message = $this->_jsonEncode($usermessage);
$message = $this->db->prepare($message);
$delivery = (!empty($when)) ? "'{$when}'":'NOW()';

Categories