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");
Related
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/>";
}
}
It is 1 AM and I am struggling for 3-4 hours to see what's wrong with my script...
My database has ~400 emails. I set $ChunkSize as counter for the loop and also to count which is the next chunk to be processed.
I've set some echo() to debug
echo "This is the " . $GLOBALS["ChunkSize"] . " chunk. <br>";
It should output what chunk is processed at that time.
If I disable mail() then I don't get 503 Service Unavailable but every echo() displays at the same time, not in the order of processing.
I also found out that some emails arrive, but not to everyone. Also, if some emails are sent, that means foreach() should have processed at least one chunk, that means it should display at least one echo().
I've set break 1; so every time it breaks out of foreach() it should display the echo() with the chunk number processed by foreach() but it doesn't.
What I am doing wrong?
$connection = mysql_connect($hostname, $username, $password);
mysql_select_db($dbname, $connection);
$result = mysql_query("SHOW COLUMNS FROM `Emails`");
while($row = mysql_fetch_array($result)){
$Addresses[] = $row['Field'];}
$Subject = "Test";
$Message = "
Test
";
$Headers = array( EMPTY FOR SECURITY REASONS );
$Headers = implode( "\r\n" , $Headers );
$ChunkAddresses = 50;
$EmailChunkArray = array_chunk($Addresses, $ChunkAddresses);
$ArraySize = count ($EmailChunkArray);
$ChunkSize = 0;
ChunkLoop: {
$EmailChunkArrayLoop = $GLOBALS["EmailChunkArray"];
foreach ($EmailChunkArrayLoop[$GLOBALS["ChunkSize"]] as $ToChunkLoop) {
if ($GLOBALS["ChunkSize"] <= $GLOBALS["ArraySize"]) {
mail($ToChunkLoop,$GLOBALS["Subject"],$GLOBALS["Message"],$GLOBALS["Headers"]);
echo "This is the " . $GLOBALS["ChunkSize"] . " chunk. <br>";
} else if ($GLOBALS["ChunkSize"] == $GLOBALS["ArraySize"]){
exit();}
$GLOBALS["ChunkSize"]++;
break 1;}
}
if ($GLOBALS["ChunkSize"] != $GLOBALS["ArraySize"]){
echo "Test. <br>";
goto ChunkLoop;
} else {
echo "Finished! <br>";}
Create script that will only do one thing - send mail.
sendMail.php
<?php
// Get recipient from the argv array
$recipient = $_SERVER['argv'][1];
// Mail args
$subject = 'HELLOOOOOOO';
$message = 'BLablabla';
$headers = [...]; // optional or not
// Send it
mail($recipient, $subject, $message, $headers);
And inside of Your code where You do:
mail($ToChunkLoop,$GLOBALS["Subject"],$GLOBALS["Message"],$GLOBALS["Headers"]);
Replace with:
$recipient = escapeshellarg($ToChunkLoop);
exec("php /path/to/sendMail.php ".$recipient." > /dev/null &"); // that will call mail script and will not wait when execution will end
Feel free to adapt my code examples as You wish
P.S. this solution is for cases when You don't want to pay for normal batch mail sending, mail subscription or dedicated, vps services and have just small web hosting. (:
P.S.. it's not a brilliant solution, but done for requirements provided by question author
I'm cycling through my emails using imap and for some reason (possibly a timeout) it reaches about 130 out of the 170 emails and cuts off.
function pop3_login($hostz,$portz,$userz,$passz,$folderz,$sslz){
$sslz=($sslz==false)?"/novalidate-cert":"";
return (imap_open("{"."$hostz:$portz/pop3$sslz"."}$folderz",$userz,$passz));
}
$msg_int = 1;
$connection = pop3_login("mail.***","110","me#me.com","***","INBOX",false);
$inbox_msg_count = imap_num_msg($connection);
while($msg_int <= $inbox_msg_count) {
echo "$msg_int OF $inbox_msg_count <br>";
$header = imap_header($connection, $msg_int);
$from = $header->reply_to;
$subject = $header->subject;
foreach ($from as $id => $object) {
$fromname = $object->personal;
$fromaddress = $object->mailbox . "#" . $object->host;
$date1 = $header->date;
$date2 = strtotime($date1);
$senddate = date("Y-m-d", $date2);
$emaildatetime = (int)date("U", $date2);
echo "Current email Scanned: ". $fromaddress . "<br>";
}
$msg_int++;
}
imap_expunge($connection);
imap_close($connection);
I was thinking it might be a timeout connection issue because it's actually running fine but just not finishing, so I've set my php.ini timeouts and waits to an absurd amount, along with imap_timeout(1,999) and imap_timeout(2,999) but it's still cutting off short (and not necessarily in the same exact position, but between 128-132ish of 170).
Any thoughts are appreciated. Thanks
I am currently trying to get the UNSEEN/UNREAD messages from my server. Currently, I have this:
$openmail = imap_open($dns, $email, $password) or die("Cannot Connect " . imap_last_error());
if ($openmail) {
/* grab emails */
$emails = imap_search($openmail, 'UNSEEN');
if ($emails) {
//For every e-mail.
$tot = imap_num_msg($openmail);
for ($i = $tot; $i > 0; $i--) {
$structure = imap_fetchstructure($openmail, $i);
if (isset($structure->parts) && is_array($structure->parts) && isset($structure->parts[1])) {
$part = $structure->parts[1];
$message = imap_fetchbody($openmail, $i, 2, FT_PEEK);
if ($part->encoding == 3) {
$message = imap_base64($message);
} else if ($part->encoding == 1) {
$message = imap_8bit($message);
} else {
$message = imap_qprint($message);
}
}
$header = imap_header($openmail, $i);
$from = imap_utf8($header->fromaddress);
$subject = $header->Subject;
$subject = substr($subject, 0, 150);
$date = $header->Date;
}
/* Print out the Unseen messages in here! */
} else {
/* No unseen messages */
echo "No unseen";
}
}
I've tried sending multiply emails to my mailserver, refreshed the page with the above script. But I keep getting the "No unseen".
I've tried to output the $emails but it's empty. It can't find anything.
If I try to just get ALL the messages (no unseen filter), I can see the emails I've sent to the mailbox, although, they're all marked as read.
Your code $message = imap_fetchbody($openmail, $i, 2, FT_PEEK); uses hardcoded part offsets, i.e. it assumes that a message is always multipart/alternative with text/plain and text/html. That's a very wrong assumption.
You have to look at the output of the BODYSTRUCTURE to see what the MIME structure of your mail is.
With that out of the way, be sure that none of your commands use the BODY fetch operation; you have to use BODY.PEEK. I have no idea how this is accessible within the PHP c-client bindings.
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.