How to remove extra non-english characters from email message? - php

I am using the following script to read emails.
<?php
//Fetch users from table
$sql_users=mysql_query("select userName, realpass,userID from users ");
while($row = mysql_fetch_assoc($sql_users)){
$username=$row['userName'].'#example.com'; // Email address is username#domain.com
$password=$row['realpass'];
$hostname = '{example.com:995/pop3/ssl/novalidate-cert}';
$username = $username; $password = $password;
$imap = imap_open($hostname,$username,$password) or die('Cannot connect: ' . imap_last_error());
for ($i = 1; $i <= $message_count; ++$i){
$header = imap_header($imap, $i);
// fetch message body and mark it as read
$body = imap_fetchbody($imap, $i,2,FT_PEEK);
$prettydate = date("jS F Y", $header->udate);
if (isset($header->from[0]->personal)) {
$personal = $header->from[0]->personal;
} else {
$personal = $header->from[0]->mailbox;
}
$subject=$header->Subject;
//display email content
$email = "$personal <{$header->from[0]->mailbox}#{$header->from[0]->host}>";
echo "On $prettydate, $email said \"$body\".\n";
echo '<br><br>';
}
print_r(imap_errors());
imap_close($imap);
}
The problem is the email message returns from extra characters with it which need to be removed. Also I need to mark the emails as read.
Here is a sample message:
"
On 20th March 2013, Joe said "email prayer content.
This =A0is a test email for example.com. It should be converted into
a n= ew prayer request.
Thanks, Joe ". "

In the PHP reference, there is a comment with a similar issue to yours. In that comment he reads the content this way:
$text = trim( utf8_encode( quoted_printable_decode(
imap_fetchbody( $this->inbox, $emailNo, $section ) ) ) );
Try adjusting that example to your code and give it a try.

Related

How to get new emails on the first try with imap_open in php

I have a PHP script which opens an email inbox, searches for the last email and then performs some other operations if this email has the UNSEEN header.
The script is run by a cron job, and it works fine. The problem is that sometimes it takes several attempts before actually finding the new email, even if the email has already arrived.
If someone sees i'm missing something, or knows how to ensure i get all emails on the first try, please let me know. This is the relevant email opening and searching code code:
//open mailbox
$inbox = imap_open('{<domain>/imap/ssl/novalidate-cert}INBOX', '<email-address>', '<password>');
$newEmails = false;
// grab a list of all the mail headers
$msgnos = imap_search($inbox, 'ALL');
$headers = imap_headers($inbox);
$last = imap_num_msg($inbox);
//check if the last email is marked as unread (U means unread)
$headerinfo = imap_headerinfo($inbox, $last);
if($headerinfo->Unseen == 'U') {
$newEmails = true;
file_put_contents("program_logs.txt","[".date('d-m-Y H:i') . "] program executed. New mails found. \r\n",FILE_APPEND);
}
echo $headerinfo->Unseen . "<br>";
//read email if the last email is unread
if($newEmails == true){
$header = imap_header($inbox, $last);
$body = imap_fetchbody($inbox, $last,1);
$structure = imap_fetchstructure($inbox, $last);
$boxname = $header->from[0]->mailbox;
$hostname = $header->from[0]->host;
$title = $header->subject;
$from = $boxname."#".$hostname;
echo "<h2>Body structure Encoding:</h2>";
var_dump($structure->encoding);
echo "<hr>";
if($structure->encoding == 3){
$body = base64_decode($body);
}
if($structure->encoding == 4){
$body=quoted_printable_decode($body);
}
echo "<h2>Is body html?</h2>";
if($body != strip_tags($body)){
echo "body is html.<br>";
$body = preg_replace( "/\n\s+/", "\n", rtrim(html_entity_decode(strip_tags($body))) );
echo "converted to plain text.";
}else{
echo "body is not html";
}
echo "<hr>";
echo "<h2>From:</h2>".$from;
echo "<hr>";
echo "<h2>Body:</h2>".$body;
echo "<hr>";
echo "<h2>title:</h2>".$title;
echo "<hr>";
file_put_contents("program_logs.txt","Email is from ".$from. " \r\n",FILE_APPEND);
}else{
echo 'No new notifications';
echo "<hr>";
echo "<h2>imap erros:</h2>";
var_dump(imap_errors());
imap_close($inbox);
echo '<hr>';
file_put_contents("program_logs.txt","[".date('d-m-Y H:i') . "] program executed, no new mails found. \r\n",FILE_APPEND);
}

Unset array value if it contains certain word

I want to unset an array value if it contains a certain word in it. What I am doing is that, I am pulling all the emails from gmail inbox and only displaying the emails from the the message body so i can update it in the database. Message body includes few emails as it is for undelivered emails.
When all the emails are displayed, it also displays where the email was sent from which i dont want.
The code is below:
/*=================================== GMAIL ======================================*/
/* connect to gmail */
//$hostname = '{imap.gmail.com:993/imap/ssl}INBOX';
$username = 'username#gmail.com';
$password = 'password';
//$inbox = imap_open($hostname,$username,$password) or die('Cannot connect to Gmail: ' . imap_last_error());
//Which folders or label do you want to access? - Example: INBOX, All Mail, Trash, labelname
//Note: It is case sensitive
$imapmainbox = "INBOX";
//Select messagestatus as ALL or UNSEEN which is the unread email
$messagestatus = "ALL";
//-------------------------------------------------------------------
//Gmail Connection String
$imapaddress = "{imap.gmail.com:993/imap/ssl}";
//Gmail host with folder
$hostname = $imapaddress . $imapmainbox;
//Open the connection
$connection = imap_open($hostname,$username,$password) or die('Cannot connect to Gmail: ' . imap_last_error());
//Grab all the emails inside the inbox
$emails = imap_search($connection,$messagestatus);
//number of emails in the inbox
$totalemails = imap_num_msg($connection);
echo "Total Emails: " . $totalemails . "<br>";
if($emails) {
//sort emails by newest first
rsort($emails);
//loop through every email int he inbox
foreach($emails as $email_number) {
//grab the overview and message
$header = imap_fetch_overview($connection,$email_number,0);
//Because attachments can be problematic this logic will default to skipping the attachments
$message = imap_fetchbody($connection,$email_number,1.1);
if ($message == "") { // no attachments is the usual cause of this
$message = imap_fetchbody($connection, $email_number, 1);
}
//split the header array into variables
$status = ($header[0]->seen ? 'read' : 'unread');
$subject = $header[0]->subject;
$from = $header[0]->from;
$date = $header[0]->date;
preg_match_all("/[\._a-zA-Z0-9-]+#[\._a-zA-Z0-9-]+/i", $message, $matches);
//$matches = array_unique($matches);
// remove some of the emails which i dont want to include
$matches[0] = remove(remove(remove(array_unique($matches[0]) , 'info#example.co.uk') , 'no-reply#example.co.uk'), '131669395#infong353.kundenserver.de') ;
foreach($matches[0] as $email) {
//echo $email . "<br>";
echo '
<div class="alert alert-primary" role="alert">
'.$email.' in <b>'.category_name(cat_id_from_email($email)).'</b> group <br><br>
<a href="index.php?p=gmail&undelivered='.$email.'" class="btn btn-info nounderline" >Undelivered</a>
<a href="index.php?p=gmail&unsubscribers='.$email.'" class="btn btn-warning nounderline" >Unsubscribers</a>
<a href="index.php?p=gmail&delete='.$email.'" class="btn btn-danger nounderline" >Delete</a>
</div>
';
}
}
}
// close the connection
imap_close($connection);
I also want to remove any email address with certain domain names. For example:
if any of the email is xxxxx#example2.com, i want to unset it. So basically any email address with example2.com.
Could anyone help me with this.
I can see two ways; remove from the array before the display loop:
$matches[0] = preg_grep('/example2\.com/', $matches[0], PREG_GREP_INVERT);
Or check in the display loop and just don't display:
foreach($matches[0] as $email) {
if(strpos($email, 'example2.com') !== false) { continue; }
//echo your stuff
}
Depends on if you want to keep the array intact but just not display or modify the array for later use.

How to set "unseen" on emails - PHP

I'm trying to make a program that takes e-mails from the post.
Everything is nice, beautiful. Almost..
Unfortunately, the problem is when the mail is "unseen". The script changes its status to "seen".
And I don't want this.
I tried to do that: at the beginning I check that emails are unseen, and at the end I'd like them to restore the status "unseen".
However, I met only with "imap_setflag_full" and it doesn't have that option.
public function pop_mails(){
$message_count = imap_num_msg($this -> _inbox);
$date = date('Y-m-d');
mkdir("./$date", 0777);
for($i=1; $i<=$message_count; $i++){
$overview = imap_fetch_overview($this->_inbox, $i);
$seen = $overview[0] -> seen;
$name = imap_utf8($overview[0]->subject);
$named = strtr($name, ":", ".");
$headers = imap_fetchheader($this->_inbox, $i, FT_PREFETCHTEXT);
$body = imap_body($this->_inbox, $i);
file_put_contents($date.'/'.$named. '.eml', $headers . "\n" . $body);
if($seen =="0") {
imap_setflag_full($this->_inbox, $seen, "\\Seen");
}
}
}
Can you help me?
You just have to clear the \\Seen Flag at the end of your process :
$status = imap_clearflag_full($this->_inbox, "$email_number", " \\Seen");

MimeMailParser Extension IMAP Setup

Currently I have an old script that parses emails, as seen here:
// Accessing the mailbox
$mailbox = imap_open("{imap.gmail.com:993/imap/ssl/novalidate-cert}INBOX", $mailbox, $mailboxPassword);
// Retrieving only unread messages
$mail = imap_search($mailbox, 'UNSEEN');
// If no new messages found aborting the script
if(empty($mail)) die('No unread emails found!');
$total_found = 0;
$skipped = 0;
// Now we loop through messages
foreach ($mail as $key => $val) {
// process everything
}
This works fine other than some encoding issues with Russian (Cyrillic) characters and a few other issues. While I could hunt down all these issues individually, it seems like there are already great mail parsing classes out there. I found this, which I'd like to use as it sounds like this gets suggested often.
The example code provided is with the parser is below.
<?php
require_once('MimeMailParser.class.php');
$path = 'path/to/mail.txt';
$Parser = new MimeMailParser();
$Parser->setPath($path);
$to = $Parser->getHeader('to');
$from = $Parser->getHeader('from');
$subject = $Parser->getHeader('subject');
$text = $Parser->getMessageBody('text');
$html = $Parser->getMessageBody('html');
$attachments = $Parser->getAttachments();
?>
However it seems to need a reference to $path which is confusing me as the emails are not stored in a folder, there pulled from IMAP. Would I add $path = $mail; in the foreach block? If not, what format do I supply the email to the parser in? Do I have to use the same script I already have and save it to a folder?
All the emails are being retrieved from Gmail. I used IMAP but could use POP instead if IMAP wont work.
Based on the suggested answer i tried this code but its just looping through x unread emails and displaying blank data for everything, headers and body?
// Accessing the mailbox
$mailbox = imap_open("{imap.gmail.com:993/imap/ssl/novalidate-cert}INBOX", $mailbox, $mailboxPassword);
// Retrieving only unread messages
$mail = imap_search($mailbox, 'UNSEEN');
// If no new messages found aborting the script
if(empty($mail)) die('No unread emails found!');
$total_found = 0;
$skipped = 0;
// Now we loop through messages
foreach ($mail as $email) {
$Parser = new MimeMailParser();
$Parser->setText($mail);
echo "-----------------------------Start Of Email---------------------------------";
echo "<br /><br /><br /><br />";
$to = $Parser->getHeader('to');
echo "To: " . $to . "<br />";
$from = $Parser->getHeader('from');
echo "From: " . $from . "<br />";
$subject = $Parser->getHeader('subject');
echo "Subject: " . $subject . "<br /><br /><br />";
//$text = $Parser->getMessageBody('text');
$html = $Parser->getMessageBody('html');
echo "Body: " . "<br /><br />" . $html . "<br />";
//$attachments = $Parser->getAttachments();
echo "<br /><br /><br /><br />";
echo "-----------------------------End Of Email---------------------------------";
}
That class has another function to set the message content directly. Just call $Parser->setText($mail) where $mail is the message content in your IMAP foreach loop.

Save web form info to xml?

I'm from a design background and only really have experience with HTML and CSS so I'm very new to anything involving PHP and can only grasp chopping and changing bits of code at best of times.
I have found some PHP code that allows me to create a web form that when used, includes the users name, email, email subject and email body - this has been tested and works just fine and I'm receiving emails from the form with no problems.
What I want to do now is have the form create/update an XML file that I have hosted with the users info every time someone uses the form.
I tried searching and couldn't really find anything that worked.
My PHP:
<?php
$ip = $_POST['ip'];
$httpref = $_POST['httpref'];
$httpagent = $_POST['httpagent'];
$visitor = $_POST['visitor'];
$visitormail = $_POST['visitormail'];
$notes = $_POST['notes'];
$attn = $_POST['attn'];
if(!$visitormail == "" && (!strstr($visitormail,"#") || !strstr($visitormail,".")))
{
echo "<h2>Use Back - Enter valid e-mail</h2>\n";
$badinput = "<h2>Feedback was NOT submitted</h2>\n";
echo $badinput;
die ("Go back! ! ");
}
if(empty($visitor) || empty($visitormail) || empty($notes )) {
echo "<h2>Use Back - fill in all fields</h2>\n";
die ("Use back! ! ");
}
$todayis = date("l, F j, Y, g:i a");
$attn = $attn ;
$subject = $attn;
$notes = stripcslashes($notes);
$message = "
Subject: $attn \n
Message: $notes \n
From: $visitor ($visitormail)\n
Additional Info : IP = $ip \n
Browser Info: $httpagent \n
";
$from = "From: $visitormail\r\n";
mail('youremail#website.com', $subject, $message, $from);
?>
I found this PHP and tried adjusting it to work with my code but it doesn't seem to work:
<?php
$file="test_xml.xml";
$visitor="Name";
$ip="IP";
//load xml object
$xml= simplexml_load_file($file);
//assign name
$xml->auth->ids = $visitor;
//assign ip
$xml->auth->key = $ip;
//store the value into the file
file_put_contents($file, $xml->asXML());
?>
Am I on the right track at all?
Just replace your XML code in your php with this one and try it out
$xml = new SimpleXMLElement('');
$mydata = $xml->addChild('VisitorInfo');
$mydata->addChild('Visitor',$Visitor);
$mydata->addChild('Key',$ip);
$mydata->PHP_EOL;
mysql_close($db);
$fp = fopen("VisitorData.xml","wb");
fwrite($fp,$xml->asXML());
fclose($fp);

Categories