My godaddy shared hosing service will not enable the IMAP extension for PHP. So I am in a pickle:
Is there a PHP function to replace the IMAP feature in PHP ?
Here is the error:
Fatal error: Call to undefined function imap_last_error()
Here is the sample code that I am having problems with:
$mbox = imap_open ('{'.$email_host.':'.$email_port.'/pop3/novalidate-cert}INBOX', $email_username, $email_password) or die(imap_last_error());
if(!$mbox){
// send email letting them know bounce checking failed?
// meh. later.
echo 'Failed to connect when checking bounces.';
}else{
$MC = imap_check($mbox);
$result = imap_fetch_overview($mbox,"1:{$MC->Nmsgs}",0);
foreach ($result as $overview) {
$this_subject = (string)$overview->subject;
//echo "#{$overview->msgno} ({$overview->date}) - From: {$overview->from} <br> {$this_subject} <br>\n";
$tmp_file = tempnam('/tmp/','newsletter_bounce');
// TODO - tmp files for windows hosting.
imap_savebody ($mbox, $tmp_file, $overview->msgno);
$body = file_get_contents($tmp_file);
if(preg_match('/Message-ID:\s*<?Newsletter-(\d+)-(\d+)-([A-Fa-f0-9]{32})/imsU',$body,$matches)){
// we have a newsletter message id, check the hash and mark a bounce.
//"message_id" => "Newsletter-$send_id-$member_id-".md5("bounce check for $member_id in send $send_id"),
$send_id = (int)$matches[1];
$member_id = (int)$matches[2];
$provided_hash = trim($matches[3]);
$real_hash = md5("bounce check for $member_id in send $send_id");
if($provided_hash == $real_hash){
$sql = "UPDATE "._DB_PREFIX."newsletter_member SET `status` = 4, bounce_time = '".time()."' WHERE `member_id` = '".$member_id."' AND send_id = '".$send_id."' AND `status` = 3 LIMIT 1";
query($sql);
imap_delete($mbox, $overview->msgno);
}else{
// bad hash, report.
}
}
unlink($tmp_file);
}
imap_expunge($mbox);
imap_close($mbox);
}
}
Thanks in advance!!
There's no PECL replacement for imap extension. If you dare, you can write one in PHP but that would be quite ineffective though. Alternative approach would be (assuming they are immune to customer's requests) to turn "GoDaddy" into "GoAwayDaddy" and change ISP to one who do not block this, quite elementary extension.
This one works on godaddy shared hosting:
http://www.phpclasses.org/package/4014-PHP-Retrieve-and-delete-messages-from-a-POP3-mailbox.html
And this one works too: http://framework.zend.com/manual/1.12/en/zend.mail.html
function __autoload($class_name) {
include $class_name . '.php';
}
include_once 'Zend/Mail/Storage/AbstractStorage.php';
include_once 'Zend/Mail/Storage/Pop3.php';
$mail = new Zend\Mail\Storage\Pop3(array('host' => '$host',
'user' => '$user',
'password' => '$password'));
echo $mail->countMessages() . " messages found\n";
foreach ($mail as $message) {
echo "Mail from '{$message->from}': {$message->subject}\n</br>";
echo $message->getContent() . "</br>";
}
Related
I have been looking a lot online but I didn't find an answer, is it possible to send encrypted emails S/MIME using PHP? if it is, how? (im using cakephp 2.x)
Thank you very much in advance
I managed to find a solution to this using PHPMailer, It applies to regular PHP as well. It will sign and encrypt the email, I couldn't find a way to do both with PHPMailer (sign and encrypt) only sign so I added some code to class.phpmailer.php. It stills need to add some error handling in case of an encryption error but so far works good.
for CakePHP 2.x:
Download PHPMailer and add it to your Vendors folder (project_name/app/vendor)
Add this line at the beginning of your function:
App::import('Vendor','PHPMailer/PHPMailerAutoload');
From here its the same for PHP or CakePHP:
$mail = new PHPMailer();
$mail->setFrom('from_who#email', 'Intranet');
//Set who the message is to be sent to
$mail->addAddress('to_who#email', 'Ricardo V');
//Set the subject line
$mail->Subject = 'PHPMailer signing test';
//Replace the plain text body with one created manually
$mail->Body = "some encrypted text...";
//Attach an image file
$mail->addAttachment('D:/path_to_file/test.pdf');
$mail->sign(
'app/webroot/cert/cert.crt', //The location of your certificate file
'app/webroot/cert/private.key', //The location of your private key
file
'password', //The password you protected your private key with (not
//the Import Password! may be empty but parameter must not be omitted!)
'app/webroot/cert/certchain.pem', //the certificate chain.
'1', //Encrypt the email as well, (1 = encrypt, 0 = dont encrypt)
'app/webroot/cert/rvarilias.crt'//The location of public certificate
//to encrypt the email with.
);
if (!$mail->send()) {
echo "Mailer Error: " . $mail->ErrorInfo;
} else {
echo "Message sent!";
}
Then we need to make some changes to class.phpmailer.php
replace the lines from 2368 to 2390 with:
$sign = #openssl_pkcs7_sign(
$file,
$signed,
'file://' . realpath($this->sign_cert_file),
array('file://' . realpath($this->sign_key_file),
$this->sign_key_pass),
null,
PKCS7_DETACHED,
$this->sign_extracerts_file
);
if ($this->encrypt_file == 1) {
$encrypted = tempnam(sys_get_temp_dir(), 'encrypted');
$encrypt = #openssl_pkcs7_encrypt(
$signed,
$encrypted,
file_get_contents($this->encrypt_cert_file),
null,
0,
1
);
if ($encrypted) {
#unlink($file);
$body = file_get_contents($encrypted);
#unlink($signed);
#unlink($encrypted);
//The message returned by openssl contains both headers
and body, so need to split them up
$parts = explode("\n\n", $body, 2);
$this->MIMEHeader .= $parts[0] . $this->LE . $this->LE;
$body = $parts[1];
} else {
#unlink($file);
#unlink($signed);
#unlink($encrypted);
throw new phpmailerException($this->lang('signing') .
openssl_error_string());
}
} else {
if ($signed) {
#unlink($file);
$body = file_get_contents($signed);
#unlink($signed);
//The message returned by openssl contains both headers
and body, so need to split them up
$parts = explode("\n\n", $body, 2);
$this->MIMEHeader .= $parts[0] . $this->LE . $this->LE;
$body = $parts[1];
} else {
#unlink($file);
#unlink($signed);
throw new phpmailerException($this->lang('signing') .
openssl_error_string());
}
}
}
then look for:
public function sign($cert_filename, $key_filename, $key_pass,
$extracerts_filename = '')
{
$this->sign_cert_file = $cert_filename;
$this->sign_key_file = $key_filename;
$this->sign_key_pass = $key_pass;
$this->sign_extracerts_file = $extracerts_filename;
}
and change it for:
public function sign($cert_filename, $key_filename, $key_pass,
$extracerts_filename = '', $and_encrypt ='0', $encrypt_cert = '')
{
$this->sign_cert_file = $cert_filename;
$this->sign_key_file = $key_filename;
$this->sign_key_pass = $key_pass;
$this->sign_extracerts_file = $extracerts_filename;
$this->encrypt_file = $and_encrypt;
$this->encrypt_cert_file = $encrypt_cert;
}
look for:
protected $sign_extracerts_file = '';
and add these lines after it:
protected $encrypt_cert = '';
protected $and_encrypt = '';
With these changes to phpmailer you can send a signed email or a signed and encrypted email. It works with attachments too.
I hope it is help ful to somebody.
*for regular php just don't add the line:
App::import('Vendor','PHPMailer/PHPMailerAutoload');
I have this weird error coming up from phpmailer (Version: 5.1 ):
exception 'phpmailerException' with message 'Could not instantiate mail function.' in C:\Inetpub\vhosts\mydomain\httpdocs\myscript\protected\components\phpmailer\class.phpmailer.php:687 Stack trace: #0 C:\Inetpub\vhosts\mydomain\httpdocs\myscript\protected\components\phpmailer\class.phpmailer.php(578): PHPMailer->MailSend('Date: Wed, 2 Oc...', '--b1_3c2b33630c...')
FYI: I am trying to send a zip file that's around 4.5MB big. But before that the script generates around 50 PDFs and adds them/creates the zip file which then gets attached to a phpmailer object and sent. (I am not using SMTP).
I know this has been asked before.. but the solutions I have found are all based on linux server involving increasing the limit on postfix.
But how do I solve this issue if the site is hosted on a windows machine ? I have plesk control panel.
Thanks in advance for your help.
[EDIT]
Here's the code snippet just incase it helps:
foreach($vars as $PDFKEY)
{
if($PDFKEY != null)
{
if((int)$PDFKEY > 0 )
{
$filename = $this->CreatePDF($PDFKEY);
$emailarr[$PDFKEY['email']][] = $filename;
$emailIdarr[$company->email][] = $PDFKEY['email'];
}
}
}
sleep(20);
//print_r($emailarr);die;
$emailTemplate = Yii::app()->params['EmailTemplate'];
$body = file_get_contents($emailTemplate);
$body = eregi_replace("[\]",'',$body);
try
{
$mail = new PHPMailer(true);
if(strtolower(Yii::app()->params['SMTPStatus']) == "enabled")
{
$mail->IsSMTP(); // telling the class to use SMTP
$mail->SMTPKeepAlive = true; // SMTP connection will not close after each email sent
$mail->Host = Yii::app()->params['SMTPHost']; // sets the SMTP server
$mail->Port = Yii::app()->params['SMTPPort']; // set the SMTP port for the GMAIL server
if(strtolower(Yii::app()->params['SMTPAuthStatus']) == "enabled")
{
$mail->SMTPAuth = true; // enable SMTP authentication
$mail->Username = Yii::app()->params['SMTPUsername']; // SMTP account username
$mail->Password = Yii::app()->params['SMTPPassword']; // SMTP account password
}
}
$mail->SetFrom(Yii::app()->params['EmailSendFrom']);
$mail->AddReplyTo(Yii::app()->params['EmailSendFrom']);
$mail->Subject = Yii::app()->params['EmailSubject'];;
$savePath = Yii::app()->params['PdfSavePath'];
$mail->AddBCC(trim(Yii::app()->params['EmailBCC']));
$b = true;
$toEmailAdded = array();
$ccEmailAdded = array();
$companyCCEmailAdded = array();
foreach($emailarr as $email=>$attachmentArr )
{
try
{
if(!in_array($email, $toEmailAdded))
{
$toEmailAdded[] = $email;
$mail->AddAddress($email);
}
if(isset($_POST['emailcc']) && strlen($_POST['emailcc']) > 0)
{
if(!in_array($_POST['emailcc'], $ccEmailAdded))
{
$ccEmailAdded[] = trim($_POST['emailcc']);
$mail->AddCC(trim($_POST['emailcc']));
}
}
$companycc = trim($emailNamearr[$email]['companyccemail']);
if(isset($companycc) && strlen($companycc) > 0)
{
foreach(explode(',',trim($companycc)) as $cc)
{
if(!in_array($cc, $companyCCEmailAdded))
{
$companyCCEmailAdded[] = trim($cc);
$mail->AddCC(trim($cc));
}
}
}
if(count($attachmentArr) > 1)
{
$zipFileName = "Archieve-".uniqid().".zip";
if($this->create_zip($attachmentArr, $zipFileName, true)) {
$mail->AddAttachment($SavePath.$zipFileName); // attachment
sleep(20);
}
} else
{
foreach($attachmentArr as $attachment)
{
$mail->AddAttachment($SavePath.$attachment); // attachment
}
}
$msgbody = str_replace("<%EMAILSENTDATE%>", date('d/m/Y', strtotime($emailNamearr[$email]['serviced'])) , $body );
if(isset($emailNamearr[$email]))
{
$msgbody = str_replace("<%CLIENTNAME%>", "for ".$emailNamearr[$email]['company'] , $msgbody );
}
else $msgbody = str_replace("<%CLIENTNAME%>", "" , $msgbody );
$mail->MsgHTML($msgbody);
try
{
$mail->Send();
}catch(Exception $e)
{
echo "<br/><br/>$e<br/><br/>".$e;die;
}
//echo "$email <br/>";
$mail->ClearAddresses();
$mail->ClearAttachments();
$mail->ClearCCs();
} catch (Exception $e) {
echo $e->getMessage(); //Boring error messages from anything else!
$b = false;
}
}
}
After tearing out quite a bit of hair on my head I think I kind of sort out the issue. Here's what I did (in case anyone else is facing the same problem )
Under IIS->My Website->error pages->Edit Features Settings By default Detailed errors for local request is selected for security purposes.
This threw the 500 error but the actual cause was hidden. By changing it to "Detailed errors" the actual error was revealed which was :
"FastCGI process exceeded" I believe by default it's 30 secs.
So even though I've max_execution_limit = 300 the process was getting stopped/failed because of the php-cgi.exe 's execution time limit.
To solve this:
edit %windir%\system32\inetsrv\config\applicationHost.config file to extend the php-cgi.exe execution time limit. set activityTimeout:3600 and requestTimeout:3600 .. i set 3600 to be on safe side and because i could.
And then the application ran just fine.
Hope this helps saving the hair on head for someone.
I think:
Yii::app()->params['SMTPStatus'] is not 'enabled'
so phpmailer uses php native mail function witch, I think, is not configured in your php.ini
Hope this helps
I am using php imap class.
In my box I have a lot of mail, but with this script I would retrieve only the unreaded mail.
How can I do it?
if ($mbox=imap_open( "{" . $mailserver . ":" . $port . "}INBOX", $user, $pass ))
{
echo "Connected\n";
} else { exit ("Can't connect: " . imap_last_error() ."\n"); echo "FAIL!\n"; };
if ($hdr = imap_check($mbox)) {
$msgCount = $hdr->Nmsgs;
echo "Ci sono ".$msgCount." mail";
} else {
echo "Failed to get mail";
}
If I do
$overview=imap_fetch_overview($mbox,"1:$msgCount",0);
the script load to an infinity time.
The imap_search UNSEEN solution is not good because pop3 don't use this flag.
So how can I do??????
Thanks a lot.
There is two way you can follow:
1. Looping through the messages
$count = imap_num_msg($connection);
for($msgno = 1; $msgno <= $count; $msgno++) {
$headers = imap_headerinfo($connection, $msgno);
if($headers->Unseen == 'U') {
... do something ...
}
}
2. Using imap_search
There's a flag called UNSEEN which you can use to search for the unread emails. You would call the imap_search function with the UNSEEN flag like so:
$result = imap_search($connection, 'UNSEEN');
If you need to combine this with more search flags, for example searching for messages from me#example.com, you could do this:
$result = imap_search($connection, 'UNSEEN FROM "me#example.com"');
For a complete list of the available flags, refer to the criteria section of the imap_search manual page on the PHP website (www.php.net/imap_search)
Source: http://www.electrictoolbox.com/php-imap-unread-messages/
This was a tough one on Google: php imap unread
The first result:
http://www.electrictoolbox.com/php-imap-unread-messages/
There's a flag called UNSEEN which you can use to search for the unread emails. You would call the imap_search function with the UNSEEN flag like so:
view sourceprint?
$result = imap_search($connection, 'UNSEEN');
If you need to combine this with more search flags, for example searching for messages from me#example.com, you could do this:
view sourceprint?
$result = imap_search($connection, 'UNSEEN FROM "me#example.com"');
For a complete list of the available flags, refer to the criteria section of the imap_search manual page on the PHP website (www.php.net/imap_search)
Edit I had read this originally as IMAP. #fail.
Google: php pop3 unread
2nd link:
function CountUnreadMails($host, $login, $passwd) {
$mbox = imap_open("{{$host}/pop3:110}", $login, $passwd);
$count = 0;
if (!$mbox) {
echo "Error";
} else {
$headers = imap_headers($mbox);
foreach ($headers as $mail) {
$flags = substr($mail, 0, 4);
$isunr = (strpos($flags, "U") !== false);
if ($isunr)
$count++;
}
}
imap_close($mbox);
return $count;
}
I am using php imap functions to parse the message from webmail. I can fetch messages one by one and save them in DB. After saving, I want to delete the inbox message. imap_delete function is not working here. My code is like that:
$connection = pop3_login($host,$port,$user,$pass,$folder="INBOX",$ssl=false);//connect
$stat = pop3_list($connection);//list messages
foreach($stat as $line) {
//save in db codes...
imap_delete($connection, $line['msgno']);//flag as delete
}
imap_close($connection, CL_EXPUNGE);
I also tested - imap_expunge($connection);
But it is not working. The messages are not deleted. Please help me out...
You are mixing POP and IMAP.
That is not going to work. You need to open the connection with IMAP. See this example:
<?php
$mbox = imap_open("{imap.example.org}INBOX", "username", "password")
or die("Can't connect: " . imap_last_error());
$check = imap_mailboxmsginfo($mbox);
echo "Messages before delete: " . $check->Nmsgs . "<br />\n";
imap_delete($mbox, 1);
$check = imap_mailboxmsginfo($mbox);
echo "Messages after delete: " . $check->Nmsgs . "<br />\n";
imap_expunge($mbox);
$check = imap_mailboxmsginfo($mbox);
echo "Messages after expunge: " . $check->Nmsgs . "<br />\n";
imap_close($mbox);
?>
Actually the functions names are like pop3. but they perform imap functionality. like -
function pop3_login($host,$port,$user,$pass,$folder="INBOX",$ssl=false)
{
$ssl=($ssl==false)?"/novalidate-cert":"";
return (imap_open("{"."$host:$port/pop3$ssl"."}$folder",$user,$pass));
}
function pop3_list($connection,$message="")
{
if ($message)
{
$range=$message;
} else {
$MC = imap_check($connection);
$range = "1:".$MC->Nmsgs;
}
$response = imap_fetch_overview($connection,$range);
foreach ($response as $msg) $result[$msg->msgno]=(array)$msg;
return $result;
}
I am trying to fetch a mail from POP3 (I am using POP3 mail server and I am trying to fetch the mail content and store into a database table for my project.), but I can't find any PHP script for that, all are only for IMAP.
Do you know how to fetch mail from a POP3 server?
Thanks.
Somewhat surprisingly, PHP's imap library can be also used for working with POP3 mailboxes. Most of the advanced IMAP features won't work, of course (e.g. folders or fetching message parts), but the basic POP3 functionality is implemented.
The main difference is the option string that you're passing to imap_open - to quote that page:
// To connect to a POP3 server on port 110 on the local server, use:
$mbox = imap_open ("{localhost:110/pop3}INBOX", "user_id", "password");
Other than that, it's fair sailing - you won't need more than imap_open, imap_num_msg, imap_body, imap_delete and imap_close for basic POP3 access.
PHP's IMAP functions can deal with both IMAP and POP3 boxes.
These functions enable you to operate with the IMAP protocol, as well as the NNTP, POP3 and local mailbox access methods.
Be warned, however, that some IMAP functions will not work correctly with the POP protocol.
there is a User Contributed Note that provides an interesting snippet. You may want to take a look at it. I can't say anything about its quality but from the surface, it looks okay.
Below, the Contributed Note:
For all the people coming here praying for:
1) a dead-easy way to read MIME attachments, or
2) a dead-easy way to access POP3 folders
Look no further.
function pop3_login($host,$port,$user,$pass,$folder="INBOX",$ssl=false)
{
$ssl=($ssl==false)?"/novalidate-cert":"";
return (imap_open("{"."$host:$port/pop3$ssl"."}$folder",$user,$pass));
}
function pop3_stat($connection)
{
$check = imap_mailboxmsginfo($connection);
return ((array)$check);
}
function pop3_list($connection,$message="")
{
if ($message)
{
$range=$message;
} else {
$MC = imap_check($connection);
$range = "1:".$MC->Nmsgs;
}
$response = imap_fetch_overview($connection,$range);
foreach ($response as $msg) $result[$msg->msgno]=(array)$msg;
return $result;
}
function pop3_retr($connection,$message)
{
return(imap_fetchheader($connection,$message,FT_PREFETCHTEXT));
}
function pop3_dele($connection,$message)
{
return(imap_delete($connection,$message));
}
function mail_parse_headers($headers)
{
$headers=preg_replace('/\r\n\s+/m', '',$headers);
preg_match_all('/([^: ]+): (.+?(?:\r\n\s(?:.+?))*)?\r\n/m', $headers, $matches);
foreach ($matches[1] as $key =>$value) $result[$value]=$matches[2][$key];
return($result);
}
function mail_mime_to_array($imap,$mid,$parse_headers=false)
{
$mail = imap_fetchstructure($imap,$mid);
$mail = mail_get_parts($imap,$mid,$mail,0);
if ($parse_headers) $mail[0]["parsed"]=mail_parse_headers($mail[0]["data"]);
return($mail);
}
function mail_get_parts($imap,$mid,$part,$prefix)
{
$attachments=array();
$attachments[$prefix]=mail_decode_part($imap,$mid,$part,$prefix);
if (isset($part->parts)) // multipart
{
$prefix = ($prefix == "0")?"":"$prefix.";
foreach ($part->parts as $number=>$subpart)
$attachments=array_merge($attachments, mail_get_parts($imap,$mid,$subpart,$prefix.($number+1)));
}
return $attachments;
}
function mail_decode_part($connection,$message_number,$part,$prefix)
{
$attachment = array();
if($part->ifdparameters) {
foreach($part->dparameters as $object) {
$attachment[strtolower($object->attribute)]=$object->value;
if(strtolower($object->attribute) == 'filename') {
$attachment['is_attachment'] = true;
$attachment['filename'] = $object->value;
}
}
}
if($part->ifparameters) {
foreach($part->parameters as $object) {
$attachment[strtolower($object->attribute)]=$object->value;
if(strtolower($object->attribute) == 'name') {
$attachment['is_attachment'] = true;
$attachment['name'] = $object->value;
}
}
}
$attachment['data'] = imap_fetchbody($connection, $message_number, $prefix);
if($part->encoding == 3) { // 3 = BASE64
$attachment['data'] = base64_decode($attachment['data']);
}
elseif($part->encoding == 4) { // 4 = QUOTED-PRINTABLE
$attachment['data'] = quoted_printable_decode($attachment['data']);
}
return($attachment);
}
you can use pop3 e-mail client class which can Access to e-mail mailboxes using the POP3 protocol.
You will get each e-mail body part and can store it in database, even you can retrieve attached files without deleting the original mail in the inbox.
For more go to http://www.phpclasses.org/package/2-PHP-Access-to-e-mail-mailboxes-using-the-POP3-protocol.html
IF you have PHP build with IMAP support, it would be easy, see IMAP documentation (especially comments at this page) at http://php.net/manual/en/book.imap.php
UPDATE: to clarify my answer - as you see in the comments and function reference, PHP imap_* functions can be used also for pop3.
You can open a socket connection and send POP3 commands directly to your server to retrieve emails.
The code below opens a connection to the server, authenticates, requests a count of available messages, downloads them one by one, then deletes them from the server. During the interaction with the server, if an unexpected response is received, the connection is closed.
You should be able to alter the code below to get what you need.
Create a config.ini file and populate it like this:
pop3_host=your.pop3.host
pop3_user=youremailusername
pop3_pass=youremailpassword
Obviously substitute the values with your actual host, username and password. Then change the parse_ini_file parameter to point to your config.ini file.
<?php
$config = parse_ini_file('/path/to/config.ini');
$stream = fsockopen('ssl://' . $config['pop3_host'], 995, $error_code, $error_message);
if (!$stream) {
die('fsockopen ' . $error_code . ' ' . $error_message);
}
$s = fgets($stream);
if (substr($s, 0, 3) !== '+OK') {
quit('OPEN');
}
chat('USER ' . $config['pop3_user']);
chat('PASS ' . $config['pop3_pass']);
$s = chat('STAT');
$stat = explode(' ', $s);
if (count($stat) !== 3) {
quit('STAT+');
}
$n = (integer)$stat[1];
for ($i = 1; $i <= $n; $i++) {
chat('RETR ' . $i);
$file = fopen($i . '.msg', 'wb');
if (!$file) {
quit('FILE ' . $i);
}
while (true) {
$s = fgets($stream);
if ($s === '.' . "\r\n") {
fclose($file);
break;
}
fputs($file, $s);
}
chat('DELE ' . $i);
}
chat('QUIT');
fclose($stream);
function chat(string $command): string {
global $stream;
fputs($stream, $command . "\r\n");
$s = fgets($stream);
if (substr($s, 0, 3) !== '+OK') {
quit(explode(' ', $command)[0]);
}
return $s;
}
function quit(string $message): void {
global $stream;
fputs($stream, 'QUIT' . "\r\n");
$s = fgets($stream);
fclose($stream);
die($message);
}