Foreign Characters in HTML Email - php

I wrote a script that takes HTML input from a web page and sends it out as an HTML email. For some reason there are foreign characters, usually exclamation points, showing up in the email that arrives in our inboxes that do not exist in the input. I've checked for hidden characters and there are none. The input is not being copied and pasted but directly entered. Here's a before and after example.
Input:
<p>Katherine Kemler, LSU flute professor, will perform at 7:30 p.m. Feb. 1 in Wattenbarger Auditorium. The performance is free and open to the public.</p>
Output: http://img42.com/LKEou
You can see the erroneous characters between Feb. and 1 and after Watt. I don't think it's the email client because it's the same in every client I've checked.
I've read some other questions around here that have led me to try things like using UTF-8 encoding instead of ISO-8859-1, using base64_encode() on the body, setting the content-transfer-encoding to 8bit but none of that has worked. I've read something about needing a line break after 998 characters but these exclamation points aren't showing up in way that suggests that to me. In my example above, one follows only ten characters after another. Here's my script:
<?php
if(!isset($_GET["id"])) return "<span class=\"text-error\">No ID specified.</span>"; //this should never happen
$id = $_GET["id"];
$ok = false;
$students = //redacted
$facstaff = //redacted
$studentsBCC = //redacted
$facstaffBCC = //redacted
$subject = "Tech Times for ".date("m/d");
$headers = "From: \"Tennessee Tech University\" <techtimes#tntech.edu>\r\n".
"Reply-to: no-reply#tntech.edu\r\n".
"MIME-Version: 1.0\r\n".
"Content-Transfer-Encoding: 8bit\r\n".
"Content-type: text/html; charset=UTF-8\r\n".//iso-8859-1\r\n".
"X-Mailer: PHP/".phpversion();
$resource = $modx->getObject("modResource", $id);
if(is_null($resource)) return "<span class=\"text-error\">Failed to get Resource $id</span>"; //this should never happen either
//get the template and insert the content
$body = $modx->getChunk("techtimes", array("copy"=>$resource->getContent(), "headerimg"=>$resource->getTVValue("headerImg")));
//check to see if this is a test run and if so reassign destination email address and empty BCCs
if(isset($_GET["email"])){
$facstaff = $_GET["email"];
$students = $_GET["email"];
$studentsBCC = "";
$facstaffBCC = "";
}
switch($id){
case 50: $ok = mail($facstaff,$subject,$body,$headers."\r\nBcc:".$facstaffBCC); break;
case 51: $ok = mail($students,$subject,$body,$headers."\r\nBcc:".$studentsBCC); break;
default: return "<span class=\"text-error\">Invalid or no ID specified for Tech Times.</span>"; //this, too, should never happen
}
if($ok){
$output = "<span class=\"text-success\">Tech Times for <strong>".(($id == 50) ? "Fac/Staff" : "students")." ($id)</strong> has been sent to <strong>".(($id == 50) ? $facstaff : $students)."</strong></span>.";
}else{ //this could happen if something goes wrong with the mailer
$error = error_get_last();
var_dump($error);
$output = "<span class=\"text-error\">Failed to send Tech Times!</span>";
}
return $output;
?>
I'm using MODx Revolution to format the output. I'm stumped.
Help?
Thanks!

Related

Few chars getting replaced with '=' in mail content in wp_mail

Whenever mails are triggered from wordpress site, a few alphabets are randomly getting replaced with '=' in the mail content. I have set the charset and content type in headers even then this weird error is coming. What could be the possible fix to this ?
Below is my code to trigger mails from wordpress site:
$footerText = "<br/><br/>
Regards,<br/>
ABC<br/><br/>
Note: This is an automated mail. Please do not reply to this message";
$post = get_post($postId);
$post_date = strtotime($post->post_date);
$author_email = get_the_author_meta( 'user_email', $post->post_author);
$headers = array();
$headers[] = 'Content-type: text/html; charset=UTF-8';
$headers[] = 'From: '.FROM_EMAIL;
//$headers[] = 'Bcc: '.$author_email;
$subject = "Request to share your expertise on - '".$post->post_title."'";
$post_title = $post->post_title;
$post_content = $post->post_content;
$post_url = get_permalink($post->ID);
$mail_message = "Your expertise would help solve complex business problems that would
help our associates solve our client problems faster.
Request you to share your expertise on the following post,
which has not been answered for over ".$days." days now.<br/><br/>
Post: <strong>".$post_title."</strong><br/>
Description: ".$post_content."<br/><br/>
Click <a href='".$post_url."'>here</a> to respond to the post.<br/><br/>
Thanks You!
".$footerText;
$hello_text = "Dear Expert,<br /><br />";
$full_message = $hello_text.$mail_message;
wp_mail('abc#gmail.com',$subject,$full_message,$headers);
Emails that i receive using this code is as follows:
Dear Expert,
Your expertise would help solve complex business p=oblems that would help our associates solve our Cli=nt(s) problems faster. Request you to share your experti=e on the following post, which has not been answered for o=er 8 days now.
Post: RFP for Business De=elopment,Functional Testing,Technology Expert,Perfecto,Healthcare,Medical =anagement,Mobile,Digital,North America This is Dynamic content, retrieved from database
Description: Customer is asking f=r RFQ to develop a new mobile app for care management application in AHM. =HM is a subsidary of Aetna Inc. This is Dynamic content, retrieved from database
Click here to respond to the post.
Thank you!
Regards, ABC
Note: This is an automated mail.=lease do not reply to this message
Totally confused on why random letters are getting replaced with '='.Kindly point out and suggest what is wrong with this
Commenting couple of return statements and replacing them as suggested in the below link on wordpress.org worked for me, now the mails are sent properly and the equal sign '=' issue is solved.
Fixed by making following changes in wp-includes\class-phpmailer.php
public function encodeQP($string, $line_max = 76)
{
// Use native function if it's available (>= PHP5.3)
if (function_exists('quoted_printable_encode')) {
//return $this->fixEOL(quoted_printable_encode($string)); commented this one
return quoted_printable_encode($string); // added this line
}
// Fall back to a pure PHP implementation
$string = str_replace(
array('%20', '%0D%0A.', '%0D%0A', '%'),
array(' ', "\r\n=2E", "\r\n", '='),
rawurlencode($string)
);
$string = preg_replace('/[^\r\n]{' . ($line_max - 3) . '}[^=\r\n]{2}/', "$0=\r\n", $string);
//return $this->fixEOL($string); commented this one
return $string; // added this line
}
Read more here: https://core.trac.wordpress.org/ticket/33815

Getting Mail body In PHP

What I am doing:
First I am trying to get email and save the reply of user in my database.
For this I am using PHP imap method to get mail from my email address.
Code:
function get_email()
{
//define server, email , password
$server = '{server.example.com:143}INBOX';
$user_name = 'login';
$user_pass = 'password';
$mail = imap_open( $server , $user_name , $user_pass );
$headers = imap_num_msg($mail);//counting the no of msg
for ($i = 1; $i <= $headers ; $i++)
{
$body = imap_fetchbody($mail, $i ,1);
$body = explode(">",$body);
$body = $body['0'];
$body = substr($body, 0, -5);
echo "<pre>";
echo "/-/-/-/-/-/".$body."/-/-/-/-/-/";
echo "</pre>";
}
// close the connection
imap_close($mail);
}
Now:
The Result that i am getting from $body = imap_fetchbody($mail, $i ,$i); is this:
Okay What new in it.
On Thu, Feb 12, 2015 at 4:56 PM, admin wrote:
> My name is admin!
>
>
but only wanted a the msg body that Okay What new in it. . So I explode() the massage and get the first element of array and remove the last line.
Problem:
I could not remove last line the current result of this program Is:
Okay What new in it.
On Thu, Feb 12, 2015 at 4:56 PM, admin
Even I have add "/-/-/-/-/-/" symbol but the symbol are not showing.
Your approach is not ideal, and this answer will not be ideal either. Because frankly what you are trying to accomplish can be quite difficult, because previous messages in a thread on emails will be different depending on client used and you cannot trust the user either (the thread below the 'body' could have been altered by the user etc.)
Using explode by '>' is not ideal, because what if it is part of the message?
exploding by \n> is a no go too because a user might inline responses as #Michael_Berkovski said.
Anyways here is my solution:
$body = preg_replace('#(\n>.*?)+$#','',$body);
This will reduce the following:
This is the body
> And this is a comment within the body
Also just the body
>Previous messages
>here
>> Even indented who cares?
to:
This is the body
> And this is a comment within the body
Also just the body
For trying very hard I come to a solution that ask user to reply with '#' at the end of the massage. As I notice there are different types of replies from different mailing services but all services show reply first.
Code:
$msgno = imap_num_msg($mail);
for ($i = 1; $i <= $msgno ; $i++)
{
$body = imap_fetchbody($mail, $i ,1);
$body = explode("#",$body);
$body = $body['0'];
echo $body;
echo "<br>";
}
From this I got my desire result.

Assigning php variables from email body

I am having a hard time figuring out where to go next.
I have set up a pipe to program on my cpanel that takes emails and sends em to a php script I have.
The script takes the email, extracts the body, and assigns the entire body to a variable called $body. What I need to do next, is take the information in the body, and make them more php variables that I can sent to an API.
The email will ALWAYS be in the same format.
This is what I get when I ask the script to send me an email of the $body variable.
--14dae934062f9d9cee04d111829f
Content-Type: text/plain; charset=ISO-8859-1
*field_1* = Illinois
*field_2* = miguel
*field_3* = martinez
*field_4* = miguel41303427#sbcglobal.net
*field_5* = 2305250033
*field_6* = streamwood
*field_7* = il
*field_8* = 2001
*field_9* = BMW
*field_10* = 325i
*field_11* = 129000
--14dae934062f9d9cee04d111829f
Content-Type: text/html; charset=ISO-8859-1
<p class="MsoNormal"><b>field_1</b> = Illinois<br>
<b>field_2</b> = miguel<br>
<b>field_3</b> = martinez<br>
<b>field_4</b> = miguel41307#sbcglobal.net<br>
<b>field_5</b> = 2305250033<br>
<b>field_6</b> = streamwood<br>
<b>field_7</b> = il<br>
<b>field_8</b> = 2001<br>
<b>field_9</b> = BMW<br>
<b>field_10</b> = 325i<br>
<b>field_11</b> = 129000<br></p>
--14dae934062f9d9cee04d111829f--
Is there a way to take the value of field_1, in this case Illinois, and assign it to say $state
It can be done with a regex. Try something like that :
if(preg_match('/<b>field\_1<\/b>(.*)<br>/', $body, $matches))
$field1 = $matches[1];
}

imap_fetchbody and stripping below line

I have a script that checks emails and puts them in a database. This works fine when new emails are composed and sent. However, if I reply to an email the imap_fetchbody does not work and it is empty.
Where am I going wrong here?
/* get information specific to this email */
$overview = imap_fetch_overview($inbox,$email_number,0);
$structure = imap_fetchstructure($inbox,$email_number);
$message = imap_fetchbody($inbox,$email_number,0);
$header = imap_headerinfo($inbox,$email_number);
//print_r($structure);
//make sure emails are read or do nothing
if($overview[0]->seen = 'read'){
//strip everything below line
$param="## In replies all text above this line is added to the ticket ##";
$strip_func = strpos($message, $param);
$message_new = substr($message,0,$strip_func );
/* output the email body */
$output.= '<div class="body">'.$message_new.'<br><br></div>';
If I output the $message instead of the $message_new so before I start stripping the text everything is displayed.
If that line "In replies..." is not present in the message at all, strpos will return boolean false, which when coerced to an integer will be 0.
So when you ask for the substring from 0 to the position, you're asking for the substring from 0 to 0, and $message_new is empty.
Check if that line is present in the mail before you try to take a substring based on it.
$param="## In replies all text above this line is added to the ticket ##";
$strip_func = strpos($message, $param);
$message_new = ($strip_func === false) ? $message : substr($message,0,$strip_func);

How to use special characters in recipients name when using PHP's mail function

How can I send an email formatted as "Name <user#example.com>" to:
ŠŒŽœžŸ¥µÀÁÃÄÅÆÇÉÊËÍÎÏÐÒÓÕÖØÙÜÝßàáâåæçèéëìíîïðñóôõöøùûýÿ <user#example.com>
Obviously, many of these characters will never show up in a name, but in case they do, I would prefer that they do not prevent an email from being successfully sent.
Currently, this fails as noted in Apache's error.log with
Ignoring invalid 'To:' recipient address
'¥µÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýÿ
' Transaction aborted: no recipients specified
If possible, I would like to keep the special characters 'as they are.'
Otherwise, can I use some sort of transliteration function to clean-up the name?
Example of usage:
<?php
$to = "ŠŒŽšœžŸ¥µÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýÿ <CHANGED#gmail.com>";
$subject = "Test Subject";
$body = "Test Body";
if (mail($to, $subject, $body)) {
echo("<p>Message successfully sent!</p>");
} else {
echo("<p>Message delivery failed...</p>");
}
?>
mb_encode_mimeheader should do it, just as shown in the example:
mb_internal_encoding('UTF-8');
$name = '山本';
$email = 'yamamoto#example.com';
$addr = mb_encode_mimeheader($name, 'UTF-8', 'Q') . " <$email>";
For better compatibility you should set the header Mime-Version: 1.0 so all mail clients understand you're using MIME encoding.
The final email headers should look like this:
To: =?UTF-8?Q?=E5=B0=81=E3=83=90=E3=83=BC?= <yamamoto#example.com>
Subject: =?UTF-8?Q?=E3=81=93=E3=82=93=E3=81=AB=E3=81=A1=E3=81=AF?=
Mime-Version: 1.0
Renders as:
To: 山本 <yamamoto#example.com>
Subject: こんにちは
Related: https://stackoverflow.com/a/13569317/476
In addition to #deceze's answer, when using Quoted Printable mode it may be necessary to escape any quotes in the name on any to/from/reply-to/etc headers:
$addr = '"'.str_replace('"', '\"', mb_encode_mimeheader($name, 'UTF-8', 'Q'))."\" <$email>";
Perhaps this isn't necessary for all MTAs, but at least for me a name with a " lead the MTA to interpret the header as multiple local addresses.
RFC-821 (2821) tells us, that all and any 8bit-data in headers field must be encoded. Base64 or QuotedPrintable, as you want and can. Most e-mail readers automatically decode encoded strings

Categories