Unset array value if it contains certain word - php

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.

Related

issues with IMAP functions php

I am facing some problem with imap function. Basically What I need to do is to read unseen mails. There will be a url in all the mails, i should fetch that URL and store.
$inbox = imap_open($hostname,$username,$password);
if($inbox)//if **1
{
/* grab emails */
$emails = imap_search($inbox,'UNSEEN');
/* if emails are returned, cycle through each... */
if($emails) //if **2
{
/* put the newest emails on top */
rsort($emails);
/* for every email... */
$varients=array("1","1.1","1.2","2");
foreach($emails as $email_number) //for loop **1
{
$ids [] = $email_number;
foreach($varients as $cur_varient) //for loop **2
{
echo "\n\nstarting with imap function number ". $cur_varient."\n\n";
$overview = imap_fetch_overview($inbox,$email_number,0);//all varients of like subject, date etc.
$from = addslashes(trim($overview[0]->from));
$inboxed_time = addslashes(trim(strtotime($overview[0]->date)));
$message = (imap_body($inbox,$email_number,$cur_varient));
print addslashes(trim($overview[0]->subject));break;
preg_match_all('#\bhttp?://[^,\s()<>]+(?:\([\w\d]+\)|([^,[:punct:]\s]|/))#', $message, $match);
$link_matched = $match[0];
$input = 'unsubscribe.php';
$linkexists = false;
foreach($link_matched as $curlink)
{
if(stripos($curlink, $input) !== false)
{
$linkexists = true;
$unsublink = $curlink;
$unsublink = str_replace('href="', '', $unsublink);
$unsublink = str_replace('"', '', $unsublink);
break;
}
}
if(isset($unsublink))
{
$unsublink = addslashes(trim(($unsublink)));
$thread = 1;
$time = date("Y-m-d H:i:s");
$iQry = " INSERT INTO `SPAMS`.url_queue VALUES(";
$iQry .= " 'default','".$unsublink."','".$thread."','";
$iQry .= "".$from."','".$inboxed_time."',UNIX_TIMESTAMP('".$time."'))";
//mysql_query($iQry);
print $iQry;
}
}//closing for loop **2
}//closing for loop **1
} //closing if **2
// Setting flag from un-seen email to seen on emails ID.
if(isset($ids))
{
imap_setflag_full($inbox,implode(",", $ids), "\\Seen \\Flagged"); //IMPORTANT
}
// colse the connection
imap_expunge($inbox);
imap_close($inbox);
}//closing if **1
I have used all different varients of imap to make sure it will read different types of mails. Now issue is, sometime the URL matched is broken. Only half URL will be fetched(I printed the entire message, saw that half URL is coming to next line). The other issue is, sometimes, the body fetched will not be the one which the current mail contains. It fetched some other mail content.
I am puzzled what to do, so putting my entire code, please help.
You will have to use a regex modifiers to match multiline texts too, or you can strip newlines and such from the body of the emails.
preg_match("/{pattern}/mi",'Testing');
//m for multiline matches and i for case-insensitive matches
Your second issue is a bit different than you'd think, emails have multiple bodies, one for simple texts, one for html, some for attachments (and their order is different in apple products).
https://www.electrictoolbox.com/php-imap-message-parts/
You are probably facing the issue of grabbing the wrong one. My recommendation would be to fetch all of the email bodies, like this:
$overview = imap_fetch_overview($this->connection, $email_number, 0);
$structure = imap_fetchstructure($this->connection, $email_number);
$message = "";
//$parts = [1, 1.1, 1.2, 2];
if (!$structure->parts)//simple email
$message .= "Simple: ". imap_fetchbody($this->connection, $email_number, 0). "<br/>";
else {
foreach ($structure->parts as $partNumber=>$part){
if ($partNumber != 0)
$message .= "Part ".$partNumber.": ". imap_fetchbody($this->connection, $email_number, $partNumber)."<br/>";
}
}

PHPmailer - Multiple sending of e-mail

I am sending emails using PHPmailer. As of now, I am successful in sending email to one address. Now, I want to send multiple emails in just one click.
PROBLEM: I have tried to use some loops below to send multiple email but I get wrong outpout. Yes, it sends email but to only one address, and the email address is getting all of the emails that are supposed to be emailed to other emails.
For example, when I send 17 emails, those 17 emails are sent to only one address. The emails should be sent according to the addresses in the database, with corresponding unique attachments. Example: abc#gmail.com should have abc.pdf attached, and 123#gmail.com should have 123.pdf attached.
I think it's in the loop. Please help me figure it out. Thanks.
require_once('phpmailer/class.phpmailer.php');
include("phpmailer/class.smtp.php");
$mail = new PHPMailer();
$body = file_get_contents('phpmailer/body.html');
$body = preg_replace('/\/b]/','',$body);
$file ='phpmailer/mailpass.txt';
if($handle = fopen($file,"r")){
$contentpass = fread($handle,'15');
fclose($handle);
}
$mail->IsSMTP();
$mail->Host = "smtp.gmail.com";
$mail->SMTPDebug = 1;
$mail->SMTPAuth = true;
$mail->SMTPSecure = "tls";
$mail->Host = "smtp.gmail.com";
$mail->Port = 587;
$mail->Username = "email#gmail.com";
$mail->Password = $contentpass;
$mail->SetFrom("email#gmail.com", "Subject");
$mail->AddReplyTo("email#gmail.com","Subject");
$mail->Subject = "Subjects";
$mail->AltBody = "Subject";
$mail->MsgHTML($body);
$file='current_schoolyear.txt';
if($handle = fopen($file,"r"))
{
$content = fread($handle,'9');
fclose($handle);
}
$input = addslashes($_POST['depchair']);
$email = "select email_address from sa_student where schoolyear = '$input'";
if ($p_address=mysql_query($email))
{
while($row = mysql_fetch_assoc($p_address))
{
$mail->AddAddress($row['email_address']);
$input = addslashes($_POST['depchair']);
$control = "select control_no from sa_student where schoolyear = '$input'";
if($ctrl=mysql_query($control)){
$ctrl_no = mysql_result($ctrl, 0);
$mail->AddAttachment("fpdf/pdf_reports/document/".$ctrl_no.".pdf");
}
else
{
echo "No attached document.";
}
if(!$mail->Send()) {
$message = "<div class=\"nNote nFailure\" >
<p>Error sending email. " . $mail->ErrorInfo ."</p>
</div>";
} else {
$message = "<div class=\"nNote nSuccess\" >
<p> Email have been sent to the examinees in ".$input_depchair. "! </p>
</div>";
}
}
}
else
{
echo (mysql_error ());
}
UPDATED CODE: After running the code below, I was able to send an email and with the correct attachment. However, there was only ONE email sent (the last email address in the database), and the rest of the emails were not sent.
$input = addslashes($_POST['depchair']);
$email = "select email_address, control_no from sa_student where schoolyear = '$input'";
if ($p_address=mysql_query($email))
{
while($row = mysql_fetch_assoc($p_address))
{
$cloned = clone $mail;
$cloned->AddAddress($row['email_address']);
$cloned->AddAttachment("fpdf/pdf_reports/document/".$row['control_no'].".pdf");
if(!$cloned->Send()) {
$message = "<div class=\"nNote nFailure\" >
<p>Error sending email. " . $mail->ErrorInfo ."</p>
</div>";
} else {
$message = "<div class=\"nNote nSuccess\" >
<p> Email have been sent to the examinees in ".$input_depchair. "! </p>
</div>";
}
unset( $cloned );
}
}
else
{
echo (mysql_error ());
}
After you send an email $mail->Send(), execute this:
$mail->ClearAllRecipients();
in your while loop.
So your basic while loop structure looks like this:
while($row = mysql_fetch_assoc($p_address)){
$mail->AddAddress($row['email_address']);
$mail->AddAttachment("fpdf/pdf_reports/document/".$ctrl_no.".pdf");
$mail->send();
$mail->ClearAllRecipients();
$mail->ClearAttachments(); //Remove all attachements
}
Within your loop, create a clone of the $mail object - before you add the recipient and attachment - then use the clone to send the email. The next loop iteration will create a new clone free of the previous address and attachment:
while($row = mysql_fetch_assoc($p_address)) {
$cloned = clone $mail;
$cloned->AddAddress($row['email_address']);
// add attchment to $cloned, etc.
if ( $cloned->send() ) { /* etc */ }
unset( $cloned );
}
This will "clear" your per-iteration changes (like address, attachment, etc) without you having to reenter config properties (like, from, host, etc.)
Addendum:
Your attachments will likely be all the same because you're not fetching new results for these lines (within your loop):
$input=addslashes($_POST['depchair']);
$control = "select control_no from sa_student where schoolyear = '$input'";
if ($ctrl=mysql_query($control)) {
$ctrl_no = mysql_result($ctrl, 0);
$mail->AddAttachment("fpdf/pdf_reports/document/".$ctrl_no.".pdf");
}
$ctrl_no will always return the same result because (I'm assuming) $_POST['depchair'] does not change - thus $input, $control, $ctrl, and $ctrl_no all remain (effectively) the same for each loop. You need to find whatever it is your actually intend to be the $ctrl_no for each loop - right now you're using the same one over and over.
The following query could probably help:
// replace
// $email = "select email_address from sa_student where schoolyear = '$input'";
// with:
$students_query = "select email_address, control_no from sa_student where schoolyear = '$input'";
// then
// if ($p_address=mysql_query($email)) {
// while($row = mysql_fetch_assoc($p_address)) {
// becomes
if ( $students=mysql_query($students_query) ) {
while ( $row = mysql_fetch_assoc( $students ) ) {
// so that finally, etc
$cloned->AddAddress($row['email_address']);
$ctrl_no = $row['control_no'];
This pulls both the student email address and their control_no in the same query, making sure they stay associated with each other through the loop. You can then get rid of the second mid-loop query, since all the results you need were pulled in the first out-of-loop query. The above isn't all the code you need to change, just the critical parts.

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

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.

Find E-Mails with an exact e-mail address on an IMAP server using PHP

I want to connect to an IMAP-server and find all E-Mails that were sent to abc#server.tld. I tried:
$mbox = imap_open("{imap.server.tld/norsh}", "imap#server.tld", "5ecure3");
$result = imap_search($mbox, "TO \"abc#server.tld\"", SE_UID);
but this also listed e-Mails that were sent e.g. to 123abc#server.tld. Is it somehow possible to do a search for exact matches?
Short answer: you can't. I didn't find anything in RFC 2060 - Internet Message Access Protocol - Version 4rev1 saying that it can be done.
But, there is a workaround. First fetch all emails that contain abc#server.tld, then iterate through the results and select only the exact matches.
$searchEmail = "abc#server.tld";
$emails = imap_search($mbox, "TO $searchEmail");
$exactMatches = array();
foreach ($emails as $email) {
// get email headers
$info = imap_headerinfo($mbox, $email);
// fetch all emails in the TO: header
$toAddresses = array();
foreach ($info->to as $to) {
$toAddresses[] = $to->mailbox . '#' . $to->host;
}
// is there a match?
if (in_array($searchEmail, $toAddresses)) {
$exactMatches[] = $email;
}
}
Now you have all emails matching abc#server.tld in $exactMatches

how can I display the contents of an email to a website?

I would like to display the body contents of an email. I have tried IMAP in php but something is VERY wrong. The IMAP isn't picking up the body of my message. It is picking up ONLY the signature in the body. So I am looking for alternative methods of reading email body contents to a webpage.
here is the original document of my email:
http://pastebin.com/WQra335P
the disclaimer/copyright blur is being grabbed by IMAP but nothing else in the body is being displayed. anyone have alternative methods of reading email from gmail or any other site that can display the contents to a webpage?
I have given up on making IMAP read it because no one has been able to figure out the problem...I have spent hours so I give up but here is the code...
<?php
/* connect to gmail */
$hostname = '{imap.gmail.com:993/imap/ssl}INBOX';
$username = 'username#gmail.com';
$password = 'password';
/* try to connect */
$inbox = imap_open($hostname,$username,$password) or die('Cannot connect to Gmail: ' . imap_last_error());
/* grab emails */
$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 */
$overview = imap_fetch_overview($inbox, $email_number, 0);
$message = imap_fetchbody($inbox, $email_number, 2);
echo $message;
echo imap_qprint($message);
$message = imap_qprint($message);
echo imap_8bit ($message);
$DateFormatted = str_replace("-0500", "", $overview[0] -> date);
/* output the email header information */
$output .= $overview[0] -> subject ;
$output .= $DateFormatted ;
//$bodyFormatted = preg_replace("/This e-mail(.*)/","",$message);
//$bodyFormatted = preg_replace("/Ce courriel(.*)/","",$bodyFormatted);
/* output the email body */
$output .= $message;
}
echo $output;
}
/* close the connection */
imap_close($inbox);
?>
In Addition to what DmitryK suggested,
Adding the below makes everything work fine without the random "=" signs. The Str_replace is used to remove the "="s generated over the pages.
$message = imap_fetchbody($inbox, $email_number, "1.1");
$message = str_replace("=", "", $message);
I dont know 100% why the "="s are generated randomly but this is most likely due to some encryption issue from the Exchange Server's side as our server is about 10 years old.
You are dealing with the multi-part messages (looking at your pastebin e-mail sample).
As a test try using this line:
$message = imap_fetchbody($inbox, $email_number, "1.1");
Plain text version lives under 1.1
HTML version is 1.2
The signature is in the next part - it is 2. And this is what you retrieve in your code sample.
Do you have access to the raw email content (the stuff with all the headers etc)
If so, try using plancacke email parser
I have used it before with good success.
$emailParser = new PlancakeEmailParser(...raw email content...);
$emailTo = $emailParser->getTo();
$emailSubject = $emailParser->getSubject();
$emailCc = $emailParser->getCc();
$emailDeliveredToHeader = $emailParser->getHeader('Delivered-To');
$emailBody = $emailParser->getPlainBody();
$emailHtml = $emailParser->getHTMLBody();
Gmail has some different IMAP settings, follow the original code more closely:
http://davidwalsh.name/gmail-php-imap

Categories