Cannot send mail using Zend library - php

require_once does not seem to work. I am trying to use Zend libraries to send mail but something does not work. I am using my web hosting server provider so I have to put the libraries in a subdirectory (without installing any framework).
// $path= dirname(__FILE__)."/ZendLibrary:".get_include_path() ;
$path= "./ZendLibrary".PATH_SEPARATOR.get_include_path() ;
set_include_path($path);
//echo $path ;
echo "Spot 0" ;
require_once 'Zend/Mail.php';
echo "Spot 1" ;
I got the "Spot 0" message but I don't get the "Spot 1" message. I have selected only two Zend libraries:
ZendLibrary/Zend/Mail/* (directory)
ZendLibrary/Zend/Mime/* (directory)
ZendLibrary/Zend/Mail.php (script)
ZendLibrary/Zend/Mime.php (script)
ZendLibrary is a folder in the same directory where my script is. What could happening?
UPDATE#1:
My problem is that the code stops working right when I run require_once. It does not echo "Spot 1" message. I have tried absolute paths for set_include_path, I have tried to load a .php library script without internal require_once statements, but nothing makes it work. As my test is run from a web hosting site in the Internet I don't have access to logs!.. or do I?
$path= realpath(dirname(__FILE__).'/ZendLibrary').PATH_SEPARATOR.get_include_path() ;
// $path= "./ZendLibrary".PATH_SEPARATOR.get_include_path() ;
set_include_path($path);

Zend Mail has some dependencies.
Hard dependencies
Zend_Exception
Zend_Loader
Zend_Mime
Zend_Validate
Soft
Zend_Locale
Zend_Date
Zend_Filter
Zend_Registry
The best is to add all Zend library to the include path in PHP and all components will load the dependencies automatically.

You havent met all the dependencies... At the minimum you also need Zend_Exception (all component specific exceptions in the framework extend form this) but im pretty sure there are others that Mail and Mime depend on. Just to make it easy on myself i would also grab Zend/Loader and use it for autoloading.
Update:
I took a look and it seems as though you will also need Zend/Validate and Zend/Loader which is required by one of the classes in Validate component - though Mail only uses Zend/Validate/Hostname (which does depend on the abstract classes and interfaces for Validate as well as Zend_Validate_Ip) so you might be able to get away with not grabbing Zend/Loader, but you might as well jsut make use of it for general purpose autoloading.
As a suggestion you could use [Swift Mailer]1 instead... youll be bale to avoid dependency hell and i like it a lot better anyhow. Only down side is its for Sending mail, while Zend_Mail will also let you read a mail store on a local or remote server.

I used Zend_Mail with SMTP standalone before, here are the files I needed. I also reduced it down to what you need if you only want to use sendmail also.
If you want to use Sendmail, that is the easiest. Your dependencies are:
Zend/Exception.php
Zend/Mail.php
Zend/Mime.php
Zend/Mail/Exception.php
Zend/Mail/Transport/Abstract.php
Zend/Mail/Transport/Exception.php
Zend/Mail/Transport/Sendmail.php
Zend/Mime/Exception.php
Zend/Mime/Message.php
Zend/Mime/Part.php
And with those files, here is an example use:
<?php
// optionally
// set_include_path(get_include_path() . PATH_SEPARATOR . '/path/to/Zend');
require_once 'Zend/Mail.php';
require_once 'Zend/Mail/Transport/Sendmail.php';
$transport = new Zend_Mail_Transport_Sendmail();
$mail = new Zend_Mail();
$mail->addTo('user#domain')
->setSubject('Mail Test')
->setBodyText("Hello,\nThis is a Zend Mail message...\n")
->setFrom('sender#domain');
try {
$mail->send($transport);
echo "Message sent!<br />\n";
} catch (Exception $ex) {
echo "Failed to send mail! " . $ex->getMessage() . "<br />\n";
}
If you need SMTP, then you have a few more dependencies as prodigitalson showed. In addition to the above you need at least:
Zend/Loader.php
Zend/Registry.php
Zend/Validate.php
Zend/Mail/Protocol/Abstract.php
Zend/Mail/Protocol/Smtp.php
Zend/Mail/Transport/Smtp.php
Zend/Validate/Abstract.php
Zend/Validate/Hostname.php
Zend/Validate/Interface.php
Zend/Validate/Ip.php
Zend/Validate/Hostname/*
Zend/Mail/Protocol/Smtp/Auth/*
Then you can do something like this:
<?php
require_once 'Zend/Mail.php';
require_once 'Zend/Mail/Transport/Smtp.php';
$config = array(//'ssl' => 'tls',
'port' => '25', //465',
'auth' => 'login',
'username' => 'user',
'password' => 'password');
$transport = new Zend_Mail_Transport_Smtp('smtp.example.com', $config);
$mail = new Zend_Mail();
$mail->addTo('user#domain')
->setSubject('Mail Test')
->setBodyText("Hello,\nThis is a Zend Mail message...\n")
->setFrom('sender#domain');
try {
$mail->send($transport);
echo "Message sent!<br />\n";
} catch (Exception $ex) {
echo "Failed to send mail! " . $ex->getMessage() . "<br />\n";
}

Answer:
My ISP (web hosting too) has a setting to disable require_once. I was able to setup a Unbuntu virtual machine on VirtualBox and set up a web server. I copied the content of my test web site in my Unbuntu and find out that require_once does work as expected !!! That may explain why the server-side include did not work for me either. The following was a usefull check, that indicated me the file was in the expected place.
$file = 'ZendLibrary/Zend/Mail.php';
if ((!is_file($file)) or (!is_readable($file)))
die("File does not exists or is not readable.");
Now I have to find out why it is disabled, how to enable it, or just switch web hosting company. Update: I had to pay $20 dolars a year more for the provider to enable PHP (in this case to be able to include).
This site can tell you more about it.

Related

Access variables or functions from other scripts in cron job via cPanel

Background
Hi,
I am new to cron jobs and I am trying to set up a test one just to see how they work. I created it in cPanel like this:
wget -O - -q https://website.com/staging/wp-content/themes/AT103/test-cron.php
My file is pretty simple so far:
<?php
$email_to = "info#domain.com";
$title = "Test title";
$body = "Test body";
mail($email_to, $title, $body);
?>
All works fine here, I recieve the email every interval that my cron job runs.
What I want
On my site people can put up ads/listings to sell their stuff. In the cron job I want to go through all listings and email the buyers and sellers for the ones that has expired. As a first step in this I need to access the variables on my website, e.g. a listing object which is put in a variable like $post. Or through a function which returns the stuff I want if easier.
What I tried
I tried to access a random file and its functions by using lots of different code examples found online. The file is in the same folder as my test-cron.php. Here are a few things I tried to put at the top of test-cron.php (one at a time, not all at once):
require '/functions.php';
require 'https://website.com/staging/wp-content/themes/AT103/functions.php';
require '/home3/username/public_html/staging/wp-content/themes/AT103/functions.php';
This all resulted in the same thing, I did not get an email anymore. So I assume there is some sort of error with the lines? I also tried with require_once() with the same result.
Questions
How do I access other scripts ("live" variables or functions) in my folder hierarchy through a cron job?
If it is not possible for some reason, can I instead access my database information somehow?
If the file to be required/included, is in the same folder as the running script you would use one of the following:
require 'functions.php'; no leading slash tells it to look in the include path, then in the current directory.
require './functions.php'; (better) the ./ explicitly says look in the current directory.
https://www.php.net/manual/en/ini.core.php#ini.include-path
EDIT:
I just realized I did not address the fact that you are using cron and that's because ...
You are sill running PHP, cronjob or not makes no difference it still works the same!
However, it can be more difficult to debug on a production server. If you want to see exactly what's happening when the script fails then you can wrap it in a try block, catch and send the error to your email, or output the error and view it in the browser.
I know on Bluehost shared-hosting, if any of my cronjobs produce any output it will be automatically sent to me via email. I use the format below, and always get an email telling me when & why it happened. While developing you can simply navigate to your test-cron.php in the browser.
<?php
try {
require './functions.php';
/*
all of your logic
*/
} catch (Error $e) {
echo "Caught Error: \n" . $e;
}

Cannot import Google App Engine Api

All I need from my server is to be able to send emails to my users when they forget their password. I try the code below after installing the Google App Engine SDK for PHP and it gives me the error
Fatal error: require_once(): Failed opening required
'google/appengine/api/mail/Message.php' (include_path='.:') in
/Library/WebServer/Documents/AppEngine/testMail.php on line 2
This is my code:
require_once 'google/appengine/api/mail/Message.php';
use google\appengine\api\mail\Message;
try {
$message = new Message();
$message->setSender('test#gmail.com');
$message->addTo('test#example.com');
$message->setSubject('Example email');
$message->setTextBody('Hello, world!');
$message->send();
echo 'Mail Sent';
} catch (InvalidArgumentException $e) {
echo 'There was an error';
}
I'm thinking that I did not install the engine properly but I'm lost at this point. Any ideas?
Well, two things. First of all, you don't need the require_once statement. At least I've never had to use that (maybe you did need it in older versions of GAE but as far as I know, it isn't needed. Your php script is currently trying to open a directory that doesn't exist in your project.) All you need is the use google\appengine\api\mail\Message; statement.
Secondly, when you setSender, you need to make sure that your email 'test#gmail.com' is a registered email in your google app engine app -> otherwise no actual email will get sent.
Hope that helps.

Is Zend\Mail\Storage\Imap.php hanging up my server?

I am trying to learn/understand Zend Framework for retrieving e-mail messages via IMAP. Our web host doesn't have the IMAP extension enabled on our web server and I have osTicket installed. I want to replace the IMAP function references in osTicket with correlating Zend_Mail references, but to do that I need to understand Zend_Mail a little better.
I have the Zend Framework 2.2.5 and have done my best to read through the documentation, but most of the documentation is really directed at prior versions and while I am doing my best to adjust to read for the updated version, there are some things I am just not understanding.
I have created a test script to get me started, but I'm not understanding what is really happening here and am hoping for a little direction. Here's my script (personal details have been obviously modified for anonymity sake):
<?php
/*******************************************************
* simple php script to verify zend mail functionality *
* *
********************************************************/
define('ROOT_DIR',$_SERVER['DOCUMENT_ROOT'].'/');
define('SUPPORT_DIR',ROOT_DIR.'support/');
define('INCLUDE_DIR',SUPPORT_DIR.'include/');
define('ZEND_DIR',INCLUDE_DIR.'zend/library/'); //ZendFramework-2.2.5
$root = ROOT_DIR;
$support = SUPPORT_DIR;
$incl = INCLUDE_DIR;
$zendir = ZEND_DIR;
var_dump($root);
echo "\n";
var_dump($support);
echo "\n";
var_dump($incl);
echo "\n";
var_dump($zendir);
echo "\n";
echo "Include Imap... ";
include_once(ZEND_DIR.'Zend/Mail/Storage/Imap.php');
if ((include_once(ZEND_DIR.'Zend/Mail/Storage/Imap.php')) !== 1)
{
echo 'Include Imap failed.';
echo "<br>";
}
chdir($zendir);
echo getcwd() . "\n";
$mail_config = array(
'host' => 'imap.gmail.com',
'user' => 'support#gmail.com',
'password' => 'password',
'ssl' => 'SSL',
'port' => 993
);
var_dump($mail_config);
echo "\n";
$mail = new Zend_Mail_Storage_Imap($mail_config);
var_dump($mail);
echo "\n";
var_dump($count = $mail->countMessages());
?>
This appears to run without any errors, except nothing happens after the include_once statement. This is what gets returned to my screen:
string(57) "/usr/home/username/public_html/domain.com/"
string(65) "/usr/home/username/public_html/domain.com/support/"
string(73)
"/usr/home/username/public_html/domain.com/support/include/"
string(86)
"/usr/home/username/public_html/domain.com/support/include/zend/library/"
Include Storage\Imap...
It doesn't show the getcwd(), or the var_dump's for either the array or the count of messages. I even tried changing my if statement verifying the include_once worked to echo a statement if it was successful and that didn't display.
Is the script getting hung up in zend\mail\storage\imap.php? What am I not doing correctly here? Like I said, I'm trying to learn it and have been searching high and low for code examples that use v2.2.5, but I obviously missing something. What is it?
EDIT:
phpinfo() did not show a location for my error logs, so I added the following to the beginning my test script:
ini_set('track_errors', 1);
error_reporting(E_ALL|E_STRICT);
error_log($php_errormsg,3,"/usr/home/username/public_html/domain.com/support/test/error_log.log");
It created the "error_log.log" file, right where it was supposed to, but it's empty and Runscope didn't see the script run?
It looks like you're trying to follow a ZF1 example but using ZF2, which is understandable, but unfortunately won't work.
Firstly, install Composer - http://getcomposer.org/ - it just makes everything easier. I'd recommend going for the 'global' installation option (which the rest of this answer will assume you've done).
In the root folder of your project, create a composer.json file (which lists the project's dependencies). In it, put:
{
"require": {
"php": ">=5.3.3",
"zendframework/zend-mail": "2.*"
}
}
this lists Zend Mail as a dependency and also PHP 5.3.3 (which ZF2 requires as a minimum).
Run composer install to install these. You'll see some output as it downloads the files. Once it's done, it should have created a folder called vendor into which it's installed the ZF2 mail class.
Your whole script can then be simplified to this:
<?php
require 'vendor/autoload.php';
$mail_config = array(
'host' => 'imap.gmail.com',
'user' => 'support#gmail.com',
'password' => 'password',
'ssl' => 'SSL',
'port' => 993
);
$mail = new \Zend\Mail\Storage\Imap($mail_config);
$count = $mail->countMessages();
var_dump($count);
You can remove the copy of ZF2 you put in zend/library/ (assuming you're not using it for anything else).

PHP script fails at $mail = new PHPMailer() without error message

This is driving me up a wall!
I'm trying to use phpmailer to send e-mail. Here is my code:
print "about to do the require!";
require_once("$s[phppath]/phpmailer.php");
print "require has been successful! creating a PHPMailer object!";
$mail = new PHPMailer();
print "yay!";
However, the program never gets to "yay", it dies at line 4 ($mail = new PHPMailer();). Most maddening is that no error message is displayed, even though php is running with display_errors = On. To test this, I threw in some obvious errors, like skipping semi-colons at the end of lines, and I immediately get an error message about this.
What the heck is going on here?
Edited
I modified the code like this:
require_once("$s[phppath]/phpmailer.php");
try {
$mail = new PHPMailer(true);
} catch (phpmailerException $e) {
echo $e->errorMessage(); //Pretty error messages from PHPMailer
} catch (Exception $e) {
echo $e->getMessage(); //Boring error messages from anything else!
}
Still no dice.
I am using PHPMailer also. Now in 2018 Version 6.05.
I was also in trouble with creation of $mail = new PHPMailer; I always saw the message that the class could not be created. But I was sure the file with the class was included.
What I found out, was that there is a namespace used within the class PHPMailer.
So the new object does not exist as "PHPMailer" but as class within the namespace PHPMailer\PHPMailer ! (not to be confused with folders of your installation).
What finally worked for me was to write the following line:
$mail = new PHPMailer\PHPMailer\PHPMailer;
// You need to add the namespace part after new and before class PHPMailer
Ok, there were two parts to this question:
1) Why no error messages? I feel very, very stupid about this one, because though I had display_errors turned on, my own script actually disabled error_reporting. Thank you Pathik Ghandi for pointing out this very simple fix. I can be quite special at times.
2) Why was PHPMailer not working? Because apparently PHPMailer now requires TWO files instead of one: class.phpmailer.php is not enough. You now also need PHPMailerAutoload.php. Hope this helps someone down the line!
Try echoing out $s[phppath] to make sure you are getting the right path. Redownload and reupload the phpMailer lib. Try using require instead of require_once. Try using include instead of require. Go into the phpmailer.php file and add in an echo or something to make sure you are actually requiring that file.
To be sure; Are you running some kind of framework? ie Wordpress? If so you may need to set a flag to show PHP error messages. WP: define("WP_DEBUG", true);
Try to call restore_error_handler() function above require.

Open local mbox mail archive with imap_open() in PHP

I'm attempting to read an mbox email archive exported from another server locally, via file access, but for whatever reason everything I've tried fails. Is there some magical trick to parse a local file and access it with PHP's built-in IMAP functionality?
You should be able to use PHP's built-in IMAP functionality. Have you tried something like this:
function openLocal($file_path) {
$mbox = imap_open("$file_path",'','');
if (!mbox) {
$errorMsg = imap_last_error(); // do something with the error...
return false;
} else {
return true;
}
}
And call this with the respective correct path:
openLocal('/home/email/temp/mailbox')
I didn't find the accepted answer sufficient, though it did point me in the right direction.
PHP's IMAP library can be used to parse local .mbox files, such as the ones from Gmail exports.
Importantly, the path must be absolute, it cannot be relative to the current folder.
$imap = imap_open($path_to_mbox, '', '');
You can then get retrieve information with imap functions, such as the subject:
$headers = imap_headerinfo($imap, 0); // Second parameter is the message number
$subject = $headers->subject;

Categories