MimeMailParser Extension IMAP Setup - php

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.

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);
}

Email Attachment from directory is not always the latest using PHPMailer

UPDATE #2 - FINAL ANSWER
I figured and you'll see in the comments below that my comparison symbol needed to be changed. So I took the code in Update #1 and simply changed this:
return filemtime($a) < filemtime($b);
to:
return filemtime($a) > filemtime($b);
And that did it!!! Thanks everyone for the dialog.
UPDATE
I've updated my code. Now I'm getting the attachment sent but again, it's not grabbing the latest one. Here's my latest code:
<?php
ini_set('display_errors',1);
ini_set('display_startup_errors',1);
error_reporting(-1);
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
require 'php/PHPMailer2020/src/Exception.php';
require 'php/PHPMailer2020/src/PHPMailer.php';
$dir = "php/sketch-drawings/";
$pics = scandir($dir);
$files = glob($dir . "*.*");
usort($files, function($a, $b){
return filemtime($a) < filemtime($b);
});
foreach ($files as $pics) {
echo '<img src="'. $pics . '">';
}
// SEND EMAIL W/ ATTACHMENT OF LATEST IMAGE
$mail = new PHPMailer();
$mail->Sender = "hello#myemail.com";
$mail->From = "mail#myemail.com";
$mail->FromName = "My Company";
$mail->AddReplyTo( "mail#mycompany.com", "DO NOT REPLY" );
//$mail->AddAddress("info#mycompany.com");
$mail->AddAddress("myemail#gmail.com");
$mail->isHTML(true);
$mail->Subject = "Latest Sketch Image";
$mail->Body = "Latest Image Attached! \n\n Thanks - XYZ Digital.";
$mail->AddAttachment($pics);
if(!$mail->Send()) {
echo 'Email Failed To Send.';
}
else {
echo 'Email Was Successfully Sent.';
echo "</p>";
echo '<script language="javascript">';
echo 'alert("Thanks! Message Sent")';
echo '</script>';
}
$mail->ClearAddresses();
?>
This issue:
The AddAttachment($filepath) returns an attachment, but it's not the most recent one-- I need it to always return the most recent image in the directory.
Here's what I'm doing:
I've created a web application that is basically a sketch pad. When a user taps on "Save" the code snaps a pic of the element saves it to a directory and then sends an email to the pre-defined address with the snap of the canvas as an attachment... and the issue is above.
What I've done:
I've looked all over the place for a solve -- seems as though the only find is around uploading the attachments via a web form--which isn't my issue. My workflow is different and why I'm here asking now. :)
What's not working:
Everything works except for the attachment part. I'm using PHPMailer but for some reason, the attachment is never the latest one. In fact, it seems to always be the same attachment no matter what.
I tried to get the first element in the array doing this (which I echo in the bottom of the code and it returns the right image:
$mail->addAttachment($sketches[0]);
this doesn't work -- it sends the email, but nothing attached.
How in the world, can I adjust my code below to get the latest attachment? I appreciate any help as PHP is not my area of expertise.
See the code below...
<?php // NEW
// DEFINE ERRORS
ini_set('display_errors',1);
ini_set('display_startup_errors',1);
error_reporting(-1);
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
require 'PHPMailer2020/src/Exception.php';
require 'PHPMailer2020/src/PHPMailer.php';
// GET LATEST UPLOAD -- AND HAVE IT STORED IN DOM (WHEN NEEDED)
$path = ('sketch-drawings');
// Sort in descending order
$sketches = scandir($path, 1);
$latest_ctime = 1;
$latest_filename = '';
$d = dir($path);
while (false !== ($entry = $d->read())) {
$filepath = "{$path}/{$entry}";
// could do also other checks than just checking whether the entry is a file
if (is_file($filepath) && filectime($filepath) > $latest_ctime) {
$latest_ctime = filectime($filepath);
$latest_filename = $entry;
}
// SEND EMAIL W/ ATTACHMENT OF LATEST IMAGE
$mail = new PHPMailer();
$mail->Sender = "hello#myemail.com";
$mail->From = "mail#myemail.com";
$mail->FromName = "My Company";
$mail->AddReplyTo( "mail#myemail.com", "DO NOT REPLY" );
//$mail->AddAddress("info#myemail.com");
$mail->AddAddress("myemail#gmail.com");
$mail->isHTML(true);
$mail->Subject = "Latest Sketch Image";
$mail->Body = "Latest Image Attached! \n\n Thanks - XYZ Digital.";
$mail->AddAttachment($filepath);
//$mail->addAttachment($sketches);
if(!$mail->Send()) {
echo 'Email Failed To Send.';
} else {
echo $filepath;
echo "<br><br>";
print $latest_filename;
echo "</p>";
echo "<p>";
print $sketches[0];
echo "</p>";
echo "<p>";
echo 'Email Was Successfully Sent.';
echo "</p>";
echo '<script language="javascript">';
echo 'alert("Thanks! Message Sent")';
echo '</script>';
}
$mail1->ClearAddresses();
}
?>
PHP's dir() function returns items in an indeterminate order. If you want to retrieve files ordered by date, see this answer.

PHP Mailer Script for sending Unlimited Mails

I am facing a problem with sending bulk emails to all my recipients (approx 10,000) It sends about 600 - 800 mails and then just stops without any reason. I am using a shared server.
Here is My Code.
<?php
#session_start();
if(!isset($_SESSION['uid'])){
echo "<html><head>";
echo "<script language=javascript>function load25(){
alert('........................You Must Login .........................');
window.location='email_login.html';}</script>";
echo "</head><body onload=load25()></body></html>";
die();
}
include "connection.php";
$uid=$_SESSION['uid'];
//var_dump($uid);
require_once('mail.message.php');
require_once('mail.info.php');
$email_id=uniqid();
$m="<html><body>";
$m.= $_POST['content'];
$subject= $_POST['subject'];
$m.="<img src='http://emailpro.in/mail/trackerimage.php?utm_source=gmail&utm_medium=email&utm_content=image&utm_campaign=services&campaignID=1&subscriberID=".$email_id."&subject=".$subject."' border='0' alt='' style='height:1px;width:1px' />";
$to1=$_POST['to'];
$username=$_POST['usid'];
$passwd=$_POST['ppwd'];
$replymailid=$_POST['repmid'];
$campname=$_POST['campname'];
//echo" $replymailid <BR> $campname";
$timezone = new DateTimeZone("Asia/Kolkata" );
$date = new DateTime();
$date->setTimezone($timezone );
$date1= $date->format( 'y/m/d H:i:s');
//echo $date1;
//$datetimee= date('y/m/d - H:i:s') ;
//date('l jS \of F Y h:i:s A');
//echo "Time Is $date ";
function nowhitespace($data)
{
return preg_replace('/\s/', '',$data);
}
$to2=nowhitespace($to1);
$b=rtrim($to2,',');
//Print_r($b);
$s=array();
$s=explode(",","$b");
$n=$_POST['no'];
//echo "The number of emails u have selected is $n<br />";
$s=array();
$s=explode(",","$b");
$s1=implode(",", $s);
$Email = new Email();
$Email->sender = $replymailid;
$Email->recipient=$s1;
$Email->subject =$subject;
$Email->message_text = "Hello!";
$Email->message_html = $m;
// send the email
$Courier = new Courier();
$sent = $Courier->send($Email);
$result=mysql_query("INSERT INTO sentmails VALUES('','$uid','$campname','$subject','$b','$n','$date1')");
/*if(isset($_POST['no'])!=" ")*/
if($n!="")
{
$rec = mysql_query("SELECT * from clientmailid where userid='$uid' limit $n");
$count = mysql_num_rows($rec);
// echo $count;
if($n!=0 && $count!=0 && $n<=$count)
{
// echo $n;
$recipients = mysql_query("SELECT * from clientmailid where userid='$uid' limit $n");
while($row = mysql_fetch_array($recipients))
{
$addresses[]= $row['emailid'];
//echo $addresses;
}
$to = implode(",", $addresses);
// print_r($to);
/* $Tos=array();
$Tos=explode(",","$to");
$Tos1=implode(",", $Tos);
*/ $Email->recipient=$to;
} else
{
echo '<html>';
echo '<head></head>';
echo '<body onload=load30()>';
echo '</body>';
echo'</html>';
echo "**Sorry You Don't have enough Email Credits**";
}
}
if ($sent != Courier::SEND_OK) {
echo "Mailer Error" ;
}
else {
if($n!=0 && $count!=0){
$n=$_POST['no'];
$recipients = mysql_query("SELECT * from clientmailid where userid='$uid' limit $n");
while($row = mysql_fetch_array($recipients))
{
$addresses[]= $row['emailid'];
$mid=$row['mid'];
$result13 = mysql_query("delete FROM clientmailid where mid='$mid' limit $n");
//echo $addresses;
}
}
echo"<script>alert('Thank u for using emailpro Your mails will be processed and will be sent shortly');</script>";
echo '<script> window.location="./dashboard.php";</script>';
}
?>
<script type="text/javascript">
function load30()
{
alert("Sorry u don't have enough email credits");
window.location='./tofill.php';
}
</script>
I know that we can send send unlimited mails through a shared server and I am sure there is something wrong either with my code or something with the server. Please guide me accordingly....
Thanks
I don't think there is anything wrong with your code, not because I can read it (please put clearer code on SO) but that it sends a random amount between 600-800 successfully. The following problems are most likely and one of them or both will solve the problem:
1) One of the potential reasons can be PHP timing out the script. Every script gets to run for a limited amount of time. If your script takes more time than that then PHP will simply kill the script. Typically that should cause an error being reported in the error logs. Check your apache error log messages - they might contain a hint.
Just add ini_set('max_execution_time', 0); in the top of your mailing script to test if this is the problem.
2) Could this be being caused by your local mail server? If you're sending out 10.000 emails in a short space of time, it might be assuming that it's spamming, and stop once you reach a certain amount. Try creating a mailing queue and sending in periodically.

Is possible serialize a PHPmailer object and use it through sessions?

Here is my problem,
I have a PHPmailer object that works fine in the file "enviar1.php",but when I serialize this object,store it in a session variable and try to unserialize and use it in another file,it doesnt work.the issue is that the email is sent,but with no subject,no body and no attachments.
File:"enviar1.php"
[...]
$email = new PHPMailer();
$email->CharSet = 'UTF-8';
$emaildes = "";
$campusEsc = addslashes($campus);
$query = "SELECT email FROM bibliotecarios WHERE campus = '$campusEsc'";
$emailBibliotecario = mysqli_query($conn,$query);
while ($row = mysqli_fetch_assoc($emailBibliotecario))
$emaildes = $row['email'];
$email->isSMTP();
$email->Host ="ssl://smtp.googlemail.com";
$email->SMTPAuth = true;
$email->Port = 465;
$email->Username = "someemail";
$email->Password = "somepass";
$email->From = "someemail";
$email->FromName = "Sistema de Encaminhamento de Ficha";
$email->AddAddress($emaildes, "bibliotecario do campus " . $campus);
$email->IsHTML(true);
$email->Subject = "ficha catalografica para revisao";
$mensagem = "<p>ficha do(a) aluno(a):" . $nome . " " . $sobrenome . "(" .$emailAluno . ") do campus de " . $campus . "</p>" ;
$mensagem .= "</br>";
$mensagem .= "</br>";
$email->Body = $mensagem;
$email->AddStringAttachment($string, 'ficha Catalografica - ' . $nome . " " . $sobrenome . '.odt');
$email->AddStringAttachment($string2, 'ficha Catalografica - ' . $nome . " " . $sobrenome . '.docx');
$email->AddAttachment($_FILES["arquivo"]["tmp_name"],$_FILES["arquivo"]["name"] );
session_start();
$_SESSION['nome'] = $nome; //I need these variables to create TBS a object in "preview.php"
$_SESSION['sobrenome'] = $sobrenome;
$_SESSION['email'] = $emailAluno;
$_SESSION['titulo'] = $titulo;
$_SESSION['subtitulo'] = $subtitulo;
$_SESSION['ano'] = $ano;
$_SESSION['folhas'] = $folhas;
$_SESSION['ilus'] = $ilus;
$_SESSION['tipo'] = $tipo;
$_SESSION['curso'] = $curso;
$_SESSION['campus'] = $campus;
$_SESSION['orientacao'] = $orientacao;
$_SESSION['coorientacao'] = $coorientacao;
$_SESSION['assunto1'] = $assunto1;
$_SESSION['assunto2'] = $assunto2;
$_SESSION['assunto3'] = $assunto3;
$_SESSION['assunto4'] = $assunto4;
$_SESSION['assunto5'] = $assunto5;
if($autorizacao != "true") //this is a checkbox from the previus form
{
if ($email->Send()) //here the email works like a charm
header("Location: preview.php");
else
echo "Erro ao enviar o email";
}
else
{
$_SESSION['emailParcial'] = serialize($email); //I stored in a session variable to edit the object later
header("Location: termo.php");//just another page with a form
}
[...]
the problem is in this file "enviar2.php",the email is sent to the correct destiny but empty,no subject,no body and none attachments.
file:"Enviar2.php"
<?php
ini_set("display_errors", true);
error_reporting(-1);
require 'configuracoes.php';
include_once('tbs_class.php');
include_once('tbs_plugin_opentbs.php');
function __autoload( $className ) {
require_once('./phpmailer/class.phpmailer.php');
}
[...]
$emailcompleto = new PHPMailer();
session_start();
$emailcompleto = unserialize($_SESSION['emailParcial']);
echo $emailcompleto->Body; //I put this to test the value and its ok
echo $emailcompleto->Subject; //the value is ok,the same as the $email object from "enviar1.php" file
if ($emailcompleto->Send()) //the email is sent but i get a empty email.
header("Location: preview.php");
else
echo "Erro ao enviar o email" . $email->ErrorInfo;
[...]
I dont know why it is not working,I used a echo and printed the Properties of the $emailcompleto object,they have correct values,it has the same subject and body of the $email object from the "enviar1.php" file has,but in the end i get a empty email.
someone have a clue of what is happening?
doc of class PHPmailer: http://www.tig12.net/downloads/apidocs/wp/wp-includes/PHPMailer.class.html#det_methods_AddAddress
It's easy....
PHPMailer can send a pre-created email if it's separated into Header and Body. PHPMailer can also create a Header and Body separate of each other:
$header = $mailer->createHeader();
$body = $mailer->createBody();
Once you have that data - you can store it in any manner you choose. Calling it up at a later time to send using any of the 3 PHPMailer Send() methods:
// SMTP
$mailer->smtpSend($header,$body);
// Sendmail
$mailer->sendmailSend($header,$body);
// PHP Mail
$mailer->mailSend($header,$body);

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.

Categories