Friends, please explain to me why PHPMailer does not send an email?
He must send a letter after payment. The usual mail() function works, but with PHPMailer I already broke my head. HELP
After payment, this file receives a notification from Yandex that the payment has been made. I made a condition that if the payment is made, then a corresponding letter is sent to the mail.
works, despite the mistake
Fatal error: Uncaught TypeError: Argument 1 passed to YandexCheckout\Model\Notification\NotificationWaitingForCapture::__construct() must be of the type array, null given, called in /home/birdyxru/public_html/test/requests.php on line 25 and defined in /home/birdyxru/public_html/test/assets/lib/Model/Notification/NotificationWaitingForCapture.php:72 Stack trace: #0 /home/birdyxru/public_html/test/requests.php(25): YandexCheckout\Model\Notification\NotificationWaitingForCapture->__construct(NULL) #1 {main} thrown in /home/birdyxru/public_html/test/assets/lib/Model/Notification/NotificationWaitingForCapture.php on line 72
<?php
ini_set('display_errors', '1');
ini_set('display_startup_errors', '1');
error_reporting(E_ALL);
require 'assets/lib/autoload.php';
require 'db/connect.php';
// Получите данные из POST-запроса от Яндекс.Кассы
$source = file_get_contents('php://input');
$requestBody = json_decode($source, true);
// Создайте объект класса уведомлений в зависимости от события
// NotificationSucceeded, NotificationWaitingForCapture,
// NotificationCanceled, NotificationRefundSucceeded
use YandexCheckout\Model\Notification\NotificationSucceeded;
use YandexCheckout\Model\Notification\NotificationWaitingForCapture;
use YandexCheckout\Model\NotificationEventType;
use YandexCheckout\Model\PaymentStatus;
try {
$notification = ($requestBody['event'] === NotificationEventType::PAYMENT_SUCCEEDED)
? new NotificationSucceeded($requestBody)
: new NotificationWaitingForCapture($requestBody);
} catch (Exception $e) {
// Обработка ошибок при неверных данных
}
// Получите объект платежа
$payment = $notification->getObject();
if($payment->getStatus() === PaymentStatus::SUCCEEDED) {
$payment_id = $payment->getId();
}
if(isset($payment_id)) {
$email = R::getCell("SELECT `email` FROM `logs` WHERE `payment_id` = '$payment_id'");
$date = R::getCell("SELECT `date` FROM `logs` WHERE `payment_id` = '$payment_id'");
$time = R::getCell("SELECT `time` FROM `logs` WHERE `payment_id` = '$payment_id'");
$report_name = strtok("$email", '#') . ' ' . $date . ' ' . $time;
// Отправка сообщения
$mailTo = $email; // Ваш e-mail
$subject = "На сайте совершен платеж"; // Тема сообщения
// Сообщение
$message = "Платеж на сумму: " . $report_name . "<br/>";
$message .= "Детали платежа: " . $payment->description . "<br/>";
$headers= "MIME-Version: 1.0\r\n";
$headers .= "Content-type: text/html; charset=utf-8\r\n";
$headers .= "From: info#site.ru <info#site.ru>\r\n";
mail($mailTo, $subject, $message, $headers);
}
?>
does not work :(
<?php
require 'assets/lib/autoload.php';
require 'db/connect.php';
require 'mailer/src/PHPMailer.php';
// Получите данные из POST-запроса от Яндекс.Кассы
$source = file_get_contents('php://input');
$requestBody = json_decode($source, true);
// Создайте объект класса уведомлений в зависимости от события
// NotificationSucceeded, NotificationWaitingForCapture,
// NotificationCanceled, NotificationRefundSucceeded
use YandexCheckout\Model\Notification\NotificationSucceeded;
use YandexCheckout\Model\Notification\NotificationWaitingForCapture;
use YandexCheckout\Model\NotificationEventType;
use YandexCheckout\Model\PaymentStatus;
try {
$notification = ($requestBody['event'] === NotificationEventType::PAYMENT_SUCCEEDED)
? new NotificationSucceeded($requestBody)
: new NotificationWaitingForCapture($requestBody);
} catch (Exception $e) {
// Обработка ошибок при неверных данных
}
// Получите объект платежа
$payment = $notification->getObject();
if($payment->getStatus() === PaymentStatus::SUCCEEDED) {
$payment_id = $payment->getId();
}
use PHPMailer\PHPMailer\PHPMailer;
if(isset($payment_id)) {
$email = R::getCell("SELECT `email` FROM `logs` WHERE `payment_id` = '$payment_id'");
$date = R::getCell("SELECT `date` FROM `logs` WHERE `payment_id` = '$payment_id'");
$time = R::getCell("SELECT `time` FROM `logs` WHERE `payment_id` = '$payment_id'");
$report_name = strtok("$email", '#') . ' ' . $date . ' ' . $time;
$mail = new PHPMailer();
//Set who the message is to be sent from
$mail->setFrom($email_admin, $from_name);
//Set an alternative reply-to address
$mail->addReplyTo($email_admin, $from_name);
//Set who the message is to be sent to
$mail->addAddress($email);
//Set the subject line
$mail->Subject = 'PHPMailer mail() test';
//Read an HTML message body from an external file, convert referenced images to embedded,
//convert HTML into a basic plain-text alternative body
$message = 'Привет ' . $report_name;
$mail->msgHTML($message);
//Replace the plain text body with one created manually
$mail->AltBody = 'This is a plain-text message body';
//Attach an image file
$mail->addAttachment('images/phpmailer_mini.png');
//send the message, check for errors
if (!$mail->send()) {
echo 'Mailer Error: ' . $mail->ErrorInfo;
} else {
echo 'Message sent!';
}
}
?>
I guess the problem is in logic or syntax
Let's explore what your error message says:
Fatal error: Uncaught TypeError: Argument 1 passed to YandexCheckout\Model\Notification\NotificationWaitingForCapture::__construct() must be of the type array, null given,
Argument 1 must be an array, but is given as null.
What is "argument 1"?
new NotificationWaitingForCapture($requestBody);
When a new object is instantiated it runs the __construct method, which the error references, so it is the line mentioned above, so this in turn means that $requestBody is the "Argument 1" and for whatever reason, holds a null value.
The PHP Manual states:
NULL is returned if the json cannot be decoded or if the encoded data is deeper than the recursion limit.
This is the cause of your issue.
Suggested Fix:
You need to check your POST data is populated, rather than simply assume it is, so update your JSON_DECODE to this:
// Получите данные из POST-запроса от Яндекс.Кассы
$source = file_get_contents('php://input');
$requestBody = json_decode($source, true);
if(empty($requestBody)){
echo "POSTED data is empty! / Опубликованные данные пусты!";
exit;
}
Note that by using PHPMailer without calling isSMTP(), you are also using mail() behind the scenes.
Without more debug info, I'm going to take a flying guess at what's wrong:
You have not set your character set.
You've got Cyrillic characters in your content, but you have not changed the character set away from the default ISO-8859-1. This is very likely to result in errors.
Assuming you're using UTF-8, you need to tell PHPMailer that like this:
$mail->CharSet = 'utf-8';
It may be working with mail() when used directly because your PHP installation may be set to use UTF-8, however, PHPMailer doesn't use that as a default as it's not always available on all platforms (e.g. if the mbstring extension is disabled).
Related
PHPMailer is working fine in a test script on it's own bare bones. However, it is crashing and not reporting an any errors on another page. I have isolated the problem to the following lines of code:
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
When I leave these lines out I get the PHP error:
Fatal error: Uncaught Error: Class 'PHPMailer' not found in /path/to/file.php:166 Stack trace: #0 {main} thrown in /path/to/file.php on line 166
When I include these lines (which I believe I need to in order to use the namespace of the imported classes) I simply get a blank white screen. Error reporting is turned on at the top of the page as follows:
error_reporting(E_ALL);
ini_set('display_errors', 1);
However, no error reports on the page.
The rest of the class files are imported as below and the path is correct as they report no errors unless I change the path.
require '../../../wp-content/plugins/PHPMailer/Exception.php';
require '../../../wp-content/plugins/PHPMailer/PHPMailer.php';
require '../../../wp-content/plugins/PHPMailer/SMTP.php';
I looked for information about use on the PHP website, however there was nothing listed when I searched (http://ca3.php.net/manual-lookup.php?pattern=use&scope=quickref).
Here is the full code in the file.php. I know there are other issues such as data input sanitization, etc, but I am refactoring someone else's code:
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
var_dump($_POST);
// PayPal Config Constants
require "../../../mail-config.php";
require "../../../keys-config.php";
/** Send HTTP POST Request for PayPal Payment */
function PPHttpPost($methodName_, $nvpStr_) {
// Get the environment set in the keys-config.php file
$environment = PAYPAL_ENVIRONMENT;
// Use the keys and endpoint for the environment
if("sandbox" === $environment || "beta-sandbox" === $environment) {
// Set the API URL
$API_Endpoint = PAYPAL_API_ENDPOINT_SANDBOX;
// Set up your API credentials, PayPal end point, and API version.
$API_UserName = urlencode(PAYPAL_API_USERNAME_SANDBOX);
$API_Password = urlencode(PAYPAL_API_PASSWORD_SANDBOX);
$API_Signature = urlencode(PAYPAL_API_SIGNATURE_SANDBOX);
} else {
// Set the API URL
$API_Endpoint = PAYPAL_API_ENDPOINT;
// Set up your API credentials, PayPal end point, and API version.
$API_UserName = urlencode(PAYPAL_API_USERNAME);
$API_Password = urlencode(PAYPAL_API_PASSWORD);
$API_Signature = urlencode(PAYPAL_API_SIGNATURE);
}
// Set the version
$version = urlencode('51.0');
// Set the curl parameters.
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $API_Endpoint);
curl_setopt($ch, CURLOPT_VERBOSE, 1);
// Turn off the server and peer verification (TrustManager Concept).
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
// Set the API operation, version, and API signature in the request.
$nvpreq = "METHOD=$methodName_&VERSION=$version&PWD=$API_Password&USER=$API_UserName&SIGNATURE=$API_Signature$nvpStr_";
// Set the request as a POST FIELD for curl.
curl_setopt($ch, CURLOPT_POSTFIELDS, $nvpreq);
// Get response from the server.
$httpResponse = curl_exec($ch);
// If the method failed
if(!$httpResponse) {
exit("$methodName_ failed: ".curl_error($ch).'('.curl_errno($ch).')');
}
// Extract the response details.
$httpResponseAr = explode("&", $httpResponse);
$httpParsedResponseAr = array();
foreach ($httpResponseAr as $i => $value) {
$tmpAr = explode("=", $value);
if(sizeof($tmpAr) > 1) {
$httpParsedResponseAr[$tmpAr[0]] = $tmpAr[1];
}
}
// If data in response is invalid
if((0 == sizeof($httpParsedResponseAr)) || !array_key_exists('ACK', $httpParsedResponseAr)) {
exit("Invalid HTTP Response for POST request($nvpreq) to $API_Endpoint.");
}
// Return the http response
return $httpParsedResponseAr;
}
// Prepare PayPal Payment Request
// Set request-specific fields.
// 'Authorization' or 'Sale'
$paymentType = urlencode('Sale');
// Name Details
$firstName = urlencode($_POST['firstname']);
$lastName = urlencode($_POST['lastname']);
// Credit Card details
$creditCardType = urlencode($_POST['customer_credit_card_type']);
$creditCardNumber = urlencode($_POST['cardnum']);
$expDateMonth = $_POST['cc_expiration_month'];
// Month must be padded with leading zero
$padDateMonth = urlencode(str_pad($expDateMonth, 2, '0', STR_PAD_LEFT));
$expDateYear = urlencode($_POST['cc_expiration_year']);
$cv = urlencode($_POST['cv']);
// Address Details
$address1 = urlencode($_POST['streetaddy']);
$city = urlencode($_POST['city']);
$state = urlencode($_POST['province']);
$postal_code = urlencode($_POST['postalcode']);
// US or other valid country code
$country = urlencode($_POST['country']);
$price = urlencode($_POST['price']);
// or other currency ('GBP', 'EUR', 'JPY', 'CAD', 'AUD')
$currencyID = urlencode('CAD');
// Add request-specific fields to the request string.
$nvpStr = "&PAYMENTACTION=$paymentType&AMT=$price&CREDITCARDTYPE=$creditCardType&ACCT=$creditCardNumber".
"&EXPDATE=$padDateMonth$expDateYear&CVV2=$cv&FIRSTNAME=$firstName&LASTNAME=$lastName".
"&STREET=$address1&CITY=$city&STATE=$state&ZIP=$postal_code&COUNTRYCODE=$country&CURRENCYCODE=$currencyID";
// Execute the API operation; see the PPHttpPost function above.
$httpParsedResponseAr = PPHttpPost('DoDirectPayment', $nvpStr);
if("SUCCESS" == strtoupper($httpParsedResponseAr["ACK"]) || "SUCCESSWITHWARNING" == strtoupper($httpParsedResponseAr["ACK"])) {
//Below line is response code from original
//exit('Direct Payment Completed Successfully: '.print_r($httpParsedResponseAr, true));
// Require the PHPMailer classes
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
require '../../../wp-content/plugins/PHPMailer/Exception.php';
require '../../../wp-content/plugins/PHPMailer/PHPMailer.php';
require '../../../wp-content/plugins/PHPMailer/SMTP.php';
//FIELDS
$first_name = $_POST['firstname'];
$last_name = $_POST['lastname'];
$email_from = $_POST['email'];
$phone = $_POST['phone'];
$ad = $_POST['ad'];
$price = $_POST['price'];
$edition = $_POST['edition'];
$issues = $_POST['issues'];
$category = $_POST['category'];
$order_id = $_POST['order_id'];
$email_message = "A Classified Ad has been purchased from the Speaker website. Details of the ad are below.\n\n";
// Filter the string
function clean_string($string) {
$bad = array("content-type","bcc:","to:","cc:","href");
return str_replace($bad,"",$string);
$string = filter_var($string, FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW);
}
// Build the Email message body contents
$email_message .= "<b>Order ID:</b> ".clean_string($order_id)."<br>";
$email_message .= "<b>First Name:</b> ".clean_string($first_name)."<br>";
$email_message .= "<b>Last Name:</b> ".clean_string($last_name)."<br>";
$email_message .= "<b>Email:</b> ".clean_string($email_from)."<br>";
$email_message .= "<b>Telephone:</b> ".clean_string($phone)."<br>";
$email_message .= "<b>Category:</b> ".clean_string($category)."<br>";
$email_message .= "<b>Ad Text:</b> ".clean_string($ad)."<br>";
$email_message .= "<b>Edition:</b> ".clean_string($edition)."<br>";
$email_message .= "<b>Number of Issues:</b> ".clean_string($issues)."<br>";
$email_message .= "<b>Price:</b> ".clean_string($price)."<br>";
// Set up the email to be sent
$mail = new PHPMailer(); // create a new object
$mail->IsSMTP(); // enable SMTP
$mail->SMTPDebug = 0;
$mail->SMTPAuth = true; // authentication enabled
$mail->SMTPSecure = 'ssl'; // secure transfer enabled REQUIRED for Gmail
$mail->Host = "smtp.gmail.com";
$mail->Port = 465; // or 587
$mail->IsHTML(true);
$mail->Username = SITE_EMAIL_SMTP_USERNAME;
$mail->Password = SITE_EMAIL_SMTP_PASSWORD;
$mail->SetFrom(SITE_EMAIL_FROM_ADRESS_LIST);
$mail->Subject = "Classified Ad Submission From The ".NEWSPAPER_NAME." Website";
$mail->Body = $email_message;
// Add all the company email addresses to the send list
foreach(PAYWALL_NOTIFICATION_EMAIL_ADDRESSES_ARRAY as $email_address){
$mail->AddAddress($email_address);
}
// Add the purchaser's email address to the send list
$mail->AddAddress($email_from);
// If mail fails to send
if(!$mail->Send()) {
//REDIRECT TO FAILED PAGE
header( 'Location: /order-not-completed' );
} else {
//REDIRECT TO SUCCESS PAGE
header( 'Location: /success' );
}
} else {
//Below line is response code for testing
exit('DoDirectPayment failed: ' . print_r($httpParsedResponseAr, true));
//REDIRECT TO FAILED PAGE
header( 'Location: /order-not-completed' );
}
?>
It will mean that your PHP version is too old. Namespaces and the use syntax were introduced in PHP 5.3, and that is already many years out of date.
PHPMailer 6.0.x requires at least PHP 5.5, so update your PHP, ideally to the latest version (currently 7.3).
Here is the page describing the use of PHP's use function to import namespaces: http://php.net/manual/en/language.namespaces.importing.php
Scoping rules for importing
The use keyword must be declared in the outermost scope of a file (the
global scope) or inside namespace declarations. This is because the
importing is done at compile time and not runtime, so it cannot be
block scoped. The following example will show an illegal use of the
use keyword:
namespace Languages;
function toGreenlandic() {
use Languages\Danish;
// ... }
Although the above code is not using the use statement in side a function, it is not at the top of the file and other functions were declared before the use statements. I tested the above code with after moving the use statements to the top of the file directly under the
In short: always put your use statements at the top of your PHP file and outside of the functions or classes.
I have a mail application that send about 5000 emails daily(a lot of account paperwork) via cron job, and works fine when the mail is sending to just one recipient. The problem comes when we activate the BCC copy, then the app starts sending until 980-1050 mails and start recieving 4.5.3 error from the smtp(Too many recipients). If i pause the job and run the cron again, the php process got a new pid, and start sending ok until it reach the same limit(980-1050 mails);
So my question is: is there a way to regenerate the php process id ?
If i was capable to do that, then the app would send those mails without problem.
Or maybe i'm missing some postfix configuration?
Relevant part of the code:
/**
* _Send_SmtpData
* Handles the SMTP negotiation for sending the email header and body.
*
* #param String $rcpt_to The 'receipt to' address to send the email to. This is a bare email address only.
* #param String $to The 'to' address to send this to. This can contain a name / email address in the standard format ("Name" <email#address>)
* #param String $subject The subject of the email to send.
* #param String $body The body of the email to send.
* #param String $headers The headers of the email to send.
**/
function _Send_SmtpData(&$rcpt_to, &$to, &$subject, &$body, &$headers)
{
$data = "DATA";
$this->DebugMemUsage('Trying to put ' . $data);
if (!$this->_Put_Smtp_Connection($data)) {
$this->ErrorCode = 12;
$this->ErrorCodeSMTPEnhanced = false;
$this->Error = GetLang('UnableToSendEmail_Data');
$this->_Close_Smtp_Connection();
$this->DebugMemUsage('Got error ' . $this->Error);
return array(false, $this->Error);
}
$response = $this->_get_response();
$this->DebugMemUsage('Got response ' . $response);
$responsecode = substr($response, 0, 3);
if ($responsecode != '354') {
$this->ErrorCode = $responsecode;
$this->ErrorCodeSMTPEnhanced = $this->_GetSMTPEnhancedErrorCode($response);
$this->Error = $response;
$this->_Close_Smtp_Connection();
$this->DebugMemUsage('Got error ' . $this->Error);
return array(false, $this->Error);
}
$msg = "To: " . $to . $this->_smtp_newline . "Subject: " . $subject . $this->_smtp_newline . $headers . $this->_smtp_newline . preg_replace('/^\.(\r|\n)/m', ' .${1}', $body);
$msg = str_replace("\r\n","\n",$msg);
$msg = str_replace("\r","\n",$msg);
$lines = explode("\n",$msg);
foreach ($lines as $no => $line) {
// we need to rtrim here so we don't get rid of tabs before the start of the line.
// the tab is extremely important for boundaries (eg sending multipart + attachment)
// so it needs to stay.
$data = rtrim($line);
$this->DebugMemUsage('Trying to put ' . $data);
if (!$this->_Put_Smtp_Connection($data)) {
$this->ErrorCode = 13;
$this->ErrorCodeSMTPEnhanced = false;
$this->Error = GetLang('UnableToSendEmail_DataWriting');
$this->_Close_Smtp_Connection();
$this->DebugMemUsage('Got error ' . $this->Error);
return array(false, $this->Error);
}
}
$data = $this->_smtp_newline . ".";
$this->DebugMemUsage('Trying to put ' . $data);
if (!$this->_Put_Smtp_Connection($data)) {
$this->ErrorCode = 14;
$this->ErrorCodeSMTPEnhanced = false;
$this->Error = GetLang('UnableToSendEmail_DataFinished');
$this->_Close_Smtp_Connection();
$this->DebugMemUsage('Got error ' . $this->Error);
return array(false, $this->Error);
}
$response = $this->_get_response();
$this->DebugMemUsage('Got response ' . $response);
$responsecode = substr($response, 0, 3);
if ($responsecode != '250') {
$this->ErrorCodeSMTPEnhanced = $this->_GetSMTPEnhancedErrorCode($response);
$this->ErrorCode = $responsecode;
$this->Error = $response;
$this->_Close_Smtp_Connection();
$this->DebugMemUsage('Got error ' . $this->Error);
return array(false, $this->Error);
}
$this->DebugMemUsage('Mail accepted ');
/**
* We got this far, this means we didn't encounter any errors.
* Cleanup previous error codes and variables since they are no longer relevant
* with the current process iteration.
*/
$this->Error = '';
$this->ErrorCode = false;
$this->ErrorCodeSMTPEnhanced = false;
$this->_smtp_email_count++;
return array(true, false);
}
In the end the "bug" was in another function, the bcc copy function; in every call for the working process, it was not cleaning the previous bcc copies of the mail, but sum them until they reach the limit.
My page continues to error out (Error 324 - Chrome) when attempting to send e-mails with attachments using PHP's PEAR Mail extension. Although the page error's out - I do receive one of the approximately 800 e-mails. Here's what I'm working with:
function email_statements($type) {
switch($type) {
// Determine the type of statement to be e-mailed
case 'monthly':
// Array holding all unique AP e-mail addresses
$ap_email_addresses = array();
include('../path/to/db/connection/params.php');
// Grab the unique AP e-mail address set to receive statements
$stmt = $mysqli->prepare("SELECT email FROM statements GROUP BY email ORDER BY email ASC");
$stmt->execute();
$stmt->bind_result($ap_email_address);
// Add unique e-mail address to AP E-mail Addresses array
while($row = $stmt->fetch()) $ap_email_addresses[] = $ap_email_address;
$stmt->close();
$mysqli->close();
// Verify we grabbed the e-mail addresses
if(count($ap_email_addresses) == 0) {
// Exit and return error code if unable to grab e-mail addresses
$return_message = 1;
exit;
}
// E-mail addresses grabbed - proceed
else {
// PDF formatted date
date_default_timezone_set('America/New_York');
$formatted_date = date('m_d_Y');
// Now we have the unique e-mail addresses - associate those with the account numbers
include('../path/to/db/connection/params.php');
foreach($ap_email_addresses as $email_address) {
$file_names = array();
$stmt = $mysqli->prepare("SELECT customer_number FROM statements WHERE email = ?");
$stmt->bind_param("s", $email_address);
$stmt->execute();
$stmt->bind_result($ap_account_number);
// Constructs the name of the statement (PDF) file to be sent
while($output = $stmt->fetch()) $file_names[] = $ap_account_number . '_' . $formatted_date . '.pdf';
// Send e-mails
include('Mail.php');
include('Mail/mime.php');
// Include SMTP authentication parameters
include('../path/to/email/info.php');
// Set the e-mail recipients
$recipients = 'example#example.com';
// Set the e-mail subject
$subject = 'Monthly Account Statement';
// Create the e-mail body
$html =
'<html>
<body>
<p>Test E-mail</p>
</body>
</html>';
// Construct the message headers
$headers = array(
'From' => $from,
'Subject' => $subject,
'Content-Type' => 'text/html; charset=UTF-8',
'MIME-Version' => '1.0'
);
$mimeparams = array();
$mimeparams['text_encoding'] = '8bit';
$mimeparams['text_charset'] = 'UTF-8';
$mimeparams['html_charset'] = 'UTF-8';
$mimeparams['head_charset'] = 'UTF-8';
// Create a new instance
$mime = new Mail_mime();
// Specify the e-mail body
$mime->setHTMLBody($html);
// Attach the statements (PDF)
foreach($file_names as $attached_file) {
$file = '../path/to/the/pdf/file/' . $attached_file;
$file_name = $attached_file;
$content_type = "Application/pdf";
$mime->addAttachment ($file, $content_type, $file_name, 1);
}
// Create the body
$body = $mime->get($mimeparams);
// Add the headers
$headers = $mime->headers($headers);
// Create SMTP connect array to be passed
$smtp = Mail::factory('smtp', array ('host' => $host, 'port' => $port, 'auth' => true, 'username' => $username, 'password' => $password));
// Send the message
$mail = $smtp->send($recipients, $headers, $body);
if(PEAR::isError($mail)) echo 'Error';
else echo 'Sent';
// Close this account and cycle through the rest
$stmt->close();
}
$mysqli->close();
}
break;
}
}
Now I thought maybe I wasn't giving the script enough time to execute - so I set it ridiculously high set_time_limit(99999999) to ensure it had plenty of time, although it normally times out within 10-15 seconds. So basically it works like this, I have an internal DB that stores customer account numbers and e-mail addresses. Accounts can have the same e-mail address (It's sent to their company's AP department) - aka one e-mail address receives statements for multiple branches. From their each statement is already constructed with the format being ACCOUNTNUMBER_MM_DD_YYYY.pdf.
So I'm simply trying to have a short message in the body, and attach the monthly statements. Again, not sure why it's failing, and even though the script halts, I do receive ONE of the e-mails (I'm sending them all to myself at the moment just to test). Can anyone see where I may have an issue?
I discovered the issue. As of PHP 5.0+ you cannot have multiple instances of the same include file - aka Mail.php was included as it looped. Once it was moved outside of the loop, the issue was resolved.
I'm trying to implement PEAR's Mail_Queue package to queue some emails for a web application. I've used the documentation at http://pear.php.net/manual/en/package.mail.mail-queue.mail-queue.tutorial.php to write a small test script.
My problem is that the database is not being updated, and it's not producing errors.
EDIT
// mail_queue db options
$db_options['type'] = 'mdb2';
$db_options['dsn'] = DSN;
$db_options['mail_table'] = 'mail_queue';
// mail_queue sending options
$mail_options['driver'] = 'smtp';
$mail_options['host'] = 'smtp.gmail.com';
$mail_options['port'] = 25;
$mail_options['localhost'] = $host;
$mail_options['auth'] = true;
$mail_options['user'] = MAILUSER;
$mail_options['pass'] = MAILPASS;
require "Queue.php";
$mail_queue =& new Mail_Queue($db_options,$mail_options);
$from = 'someone#domain.ca';
$to = 'martin#starmedia.ca';
$message = 'This is a test';
$headers = array('From' => $from,
'To' => $to,
'Subject' => 'Someone has sent you an email!');
$mime =& new Mail_mime();
$mime->setTXTBody($message);
$body = $mime->get();
$headers = $mime->headers($headers,true);
print $mail_queue->put($from,$to,$headers,$body);
This produces the error Mail Queue Error: Cannot connect to database . However I checked all of the connection information and it's correct. Also, adding if (PEAR::isError($mail)) die($mail->getMessage()); produces no errors!
OK, I finally have my mail queue file working. Here are the steps I took to get it to function:
1. Enable error messages
To enable error handling, I added this snippet:
function handle_pear_error($e) {
die($e->getMessage() . ' ' . print_r($e->getUserInfo(), true));
}
PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, 'handle_pear_error');
Once I added this, I reloaded the page and I was getting the following error:
Call to undefined function: MDB2_Driver_mysql::_isNewLinkSet()
2. Update MDB2's MySQL driver
I searched that error and found that it's usually a result of either not having an up-to-date MDB2 library or its MySQL driver.
So I updated both and it's working!
I'm new to using EWS from Exchangeclient classes.
I'm looking for a simple example how to send an email with an attachment. I've found examples about how to send an email but not sending an email with an attachment.
This is my script:
$exchangeclient = new Exchangeclient();
$exchangeclient->init($username, $password, NULL, 'ews/Services.wsdl');
$exchangeclient->send_message($mail_from, $subject, $body, 'HTML', true, true);
function - PHP Classes:
function send_message($to, $subject, $content, $bodytype="Text", $saveinsent=true, $markasread=true) {
$this->setup();
if($saveinsent) {
$CreateItem->MessageDisposition = "SendOnly";
$CreateItem->SavedItemFolderId->DistinguishedFolderId->Id = "sentitems";
}
else
$CreateItem->MessageDisposition = "SendOnly";
$CreateItem->Items->Message->ItemClass = "IPM.Note";
$CreateItem->Items->Message->Subject = $subject;
$CreateItem->Items->Message->Body->BodyType = $bodytype;
$CreateItem->Items->Message->Body->_ = $content;
$CreateItem->Items->Message->ToRecipients->Mailbox->EmailAddress = $to;
if($markasread)
$CreateItem->Items->Message->IsRead = "true";
$response = $this->client->CreateItem($CreateItem);
$this->teardown();
if($response->ResponseMessages->CreateItemResponseMessage->ResponseCode == "NoError")
return true;
else {
$this->lastError = $response->ResponseMessages->CreateItemResponseMessage->ResponseCode;
return false;
}
}
You have to first save the email as a draft (with the appropriate message disposition), then CreateAttachment() so it has an attachment, then edit it with UpdateItem() so the message disposition is SendOnly. Then it will be sent.
See David Sterling's reply on this thread: http://social.technet.microsoft.com/Forums/en-US/exchangesvrdevelopment/thread/f7d5257e-ec98-40fd-b301-f378ba3080fd/ (It's about Meeting Requests but they work the same way.)