I am using PHPMailer to send email to my clients. But I am not satisfied with the output of the
I want to remove <michael#gmail.com> at the end of my name but not sure how to do it.
My current script:
$mail->SetFrom("michael#gmail.com",'Michael Chu');
$mail->XMailer = 'Microsoft Mailer';
$mail->AddAddress($email);
$mail->Subject = "TEST Email";
$mail->Body = "<p>TEST Email<p>";
The relevant parts in the PHPMailer code is in the Pre Send routine, which assembles the mail (and which is obviously called internally always before send):
public function preSend() {
...
try {
$this->error_count = 0; // Reset errors
$this->mailHeader = '';
...
// Create body before headers in case body makes changes to headers (e.g. altering transfer encoding)
$this->MIMEHeader = '';
$this->MIMEBody = $this->createBody();
// createBody may have added some headers, so retain them
$tempheaders = $this->MIMEHeader;
$this->MIMEHeader = $this->createHeader();
$this->MIMEHeader .= $tempheaders;
...
return true;
This will be called always. Now: when we look at the createHeader-function we see this:
public function createHeader()
{
$result = '';
...
$result .= $this->addrAppend('From', [[trim($this->From), $this->FromName]]);
...
return $result;
}
So: Create Header always adds the From Address part, but it relies on addrAppend to format it (passing 'From' and an array containing one address-array [email, name])
public function addrAppend($type, $addr)
{
$addresses = [];
foreach ($addr as $address) {
$addresses[] = $this->addrFormat($address);
}
return $type . ': ' . implode(', ', $addresses) . static::$LE;
}
The address-array is passed on:
public function addrFormat($addr)
{
if (empty($addr[1])) { // No name provided
return $this->secureHeader($addr[0]);
}
return $this->encodeHeader($this->secureHeader($addr[1]), 'phrase') .
' <' .
$this->secureHeader($addr[0])
. '>';
}
and formatted with the email... Nothing you can do about it.
So with phpmailer you can't do it. But you can write your own subclass.
Probably something along those lines
<?php
//Import PHPMailer classes into the global namespace
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
require '../vendor/autoload.php';
/**
* Use PHPMailer as a base class and extend it
*/
class myPHPMailer extends PHPMailer
{
public function addrFormat($addr)
{
if (empty($addr[1])) { // No name provided
return $this->secureHeader($addr[0]);
}
else {
return $this->secureHeader($addr[1]);
}
}
}
Related
We can count unseen messages with:
$unreadMessages = $mail->countMessages([Storage::FLAG_UNSEEN]);
How to iterate only those unseen messages?
When I iterate all messages (as shown in documentation), it's painfully slow.
foreach ($mail as $messageNum => $message) {
if ($message->hasFlag(Storage::FLAG_SEEN) && !$message->hasFlag(Storage::FLAG_UNSEEN) && !$message->hasFlag(Storage::FLAG_RECENT)) {
// echo PHP_EOL . PHP_EOL . "Skipping seen/not-recent e-mail from " . $message->from . PHP_EOL;
continue;
}
}
Thanks.
When you look into how countMessages() function is done, you find out that protocol search function can be used. But protocol is private. So you have to extend the class:
class MyImap extends Laminas\Mail\Storage\Imap
{
public function getProtocol()
{
return $this->protocol;
}
}
$mail = new MyImap(...);
Then you can use this for fast iterating only unseen messages:
$message_nums = $mail->getProtocol()->search(['UNSEEN']);
foreach ($message_nums as $messageNum) {
$message = $mail->getMessage($messageNum);
}
I am trying to send attachments with SendGrid through PHP, but keep getting a corrupted file error when I open the attachment. The error message "We're sorry. We can't open 'file.docx' because we found a problem with its contents" and when I click on the details of the error I see "The file is corrupt and cannot be opened"
My code looks like the below:
$sendGridLoginInfo = $contactViaEmail->getSendGridLoginInfo();
$sendgrid = new SendGrid($sendGridLoginInfo['Username'], $sendGridLoginInfo['Password']);
$mail = new SendGrid\Mail();
//Add the tracker args
$mail->addUniqueArgument("EmailID", $emailID);
$mail->addUniqueArgument("EmailGroupID", $emailGroupID);
/*
* INSERT THE SUBSITUTIONS FOR SEND GRID
*/
foreach ($availableSubstitutions as $availableSubstitution)
{
$mail->addSubstitution("[[" . $availableSubstitution . "]]", $substitutions[$availableSubstitution]);
}
/*
* ADD EACH EMAIL AS A NEW ADD TO
* This makes it BCC (because each person gets their own copy) and each person gets their own individualized email.
*/
foreach ($emailInfo['SendToEmailAddress'] as $toEmail)
{
if ($sendToLoggedInUser)
{
$mail->addTo($adminEmailAddress);
}
else
{
$mail->addTo($toEmail);
}
$trashCount++;
}
//Set the subject
$mail->setSubject($emailInfo['EmailSubject']);
//Instantiate the HTML Purifier (for removing the html)
$config = HTMLPurifier_Config::createDefault();
$config->set('HTML', 'Allowed', '');
$purifier = new HTMLPurifier($config);
$mail->setText($purifier->purify($emailBody));
$mail->setHtml($emailBody);
if ($emailInfo['AttachmentID'])
{
$sql = "SELECT
AttachmentPath
FROM
EmailAttachments
WHERE
EmailAttachments.AttachmentID = :attachmentID";
if ($query = $pdoLink->prepare($sql))
{
$bindValues = array();
$bindValues[":attachmentID"] = $emailInfo['AttachmentID'];
if ($query->execute($bindValues))
{
if ($row = $query->fetch(\PDO::FETCH_ASSOC))
{
$attachment = "";
$mail->addAttachment($sitedb . $row['AttachmentPath']);
}
}
}
}
if ($sendToLoggedInUser)
{
$mail->setFrom($adminEmailAddress);
$mail->setReplyTo($adminEmailAddress);
}
else
{
$mail->setFrom($emailInfo['FromAddress']);
$mail->setReplyTo($emailInfo['ReplyTo']);
}
$mail->setFromName($emailInfo['FromName']);
$sendgrid->web->send($mail);
I've played with the content type and everything else that I can think of and just cannot find out what is causing the attachments to be corrupted.
You need to create an attachment object to add an attachment, you can't use the path directly like you are. SendGrid requires files to be sent as base64 encoded strings.
You'll need to create the attachment object, you could do this as a method:
public function getAttachment($path)
{
if (!file_exists($path)) {
return false;
}
$attachment = new SendGrid\Attachment;
$attachment->setContent(base64_encode(file_get_contents($path)));
$attachment->setType(mime_content_type($path));
$attachment->setFilename(basename($path));
$attachment->setDisposition('attachment');
return $attachment;
}
Then add it to your email:
$attachment = $this->getAttachment($sitedb . $row['AttachmentPath']);
if ($attachment instanceof SendGrid\Attachment) {
$mail->addAttachment($attachment);
}
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');
So I am using the PHPMailer library in PHP to send a welcome email when ever my users registered, and it takes so long to do this.
It takes around 30 - 50 seconds to actually load the home page, after clicking submit on the registration. It basically puts the page in a reloading state for over 30 seconds.
The code I use is below...
if ($config['user']['welcome_email_enabled'])
$autoLoader->getLibrary('mail')->sendWelcomeEmail($email, $username);
And my mail library is here.
<?php
/**
* MangoCMS, content management system.
*
* #info Handles the mail functions.
* #author Liam Digital <liamatzubbo#outlook.com>
* #version 1.0 BETA
* #package MangoCMS_Master
*
*/
defined("CAN_VIEW") or die('You do not have permission to view this file.');
class mangoMail {
private $phpMailer;
public function assignMailer($phpMailer) {
$this->phpMailer = $phpMailer;
}
public function setupMail($username, $password, $eHost) {
if ($this->phpMailer == null)
return;
$this->phpMailer->isSMTP();
$this->phpMailer->Host = $eHost;
$this->phpMailer->SMTPAuth = true;
$this->phpMailer->Username = $username;
$this->phpMailer->Password = $password;
$this->phpMailer->SMTPSecure = 'tls';
$this->phpMailer->Port = 587;
}
public function sendMail() {
if ($this->phpMailer == null)
return;
if (!$this->phpMailer->send()) {
echo 'Message could not be sent.';
echo 'Mailer Error: ' . $this->phpMailer->ErrorInfo;
exit();
}
else {
echo 'Email has been sent.';
}
}
public function setFrom($from, $fromTitle) {
$this->phpMailer->setFrom($from, $fromTitle);
}
public function addAddress($address) {
$this->phpMailer->addAddress($address);
}
public function setSubject($subject) {
$this->phpMailer->Subject = $subject;
}
public function setBody($body) {
$this->phpMailer->Body = $body;
}
public function setAltBody($altBody) {
$this->phpMailer->AltBody = $altBody;
}
public function setHTML($html) {
$this->phpMailer->isHTML($html);
}
public function addReply($email, $name = '') {
$this->phpMailer->addReplyTo($email, $name);
}
public function sendWelcomeEmail($email, $username) {
global $config;
$mailer = $this->phpMailer;
$mailer->setFrom($config['website']['email'], $config['website']['owner']);
$mailer->addAddress($email, $username);
$mailer->addReplyTo($config['website']['email'], 'Reply Here');
$mailer->isHTML(true);
$mailer->Subject = 'Welcome to ' . $config['website']['name'] . ' (' . $config['website']['link'] . ')';
$mailer->Body = '<div style="background-color:#1a8cff;padding:24px;color:#fff;border-radius:3px;">
<h2>Welcome to Zubbo ' . $username . '!</h2>Thank you for joining the Zubbo community, we offer spectacular events, opportunities, and entertainment.<br><br>When you join Zubbo you will recieve <b>250,000 credits</b>, <b>100,000 duckets</b>, and <b>5 diamonds</b>. One way to earn more is by being online and active, the more you are active the more you will earn, other ways are competitions, events, and games :)<br><br>We strive to keep the community safe and secure, so if you have any questions or concerns or have found a bug please reply to this email or contact us using in-game support.<br><br>Thank you for joining Zubbo Hotel!<br>- Zubbo Staff Team
</div>';
$mailer->AltBody = 'Here is a alt body...';
if (!$mailer->send()) {
exit('FAILED TO SEND WELCOME EMAIL!! ' . $mailer->ErrorInfo);
}
}
}
?>
So I call these to start with, then the sendWelcomeEmail() when I want to actually send the email.
$mailer->assignMailer(new PHPMailer());
and
$mailer->setupMail(
"********#gmail.com",
"**************",
"smtp.gmail.com");
Why is it taking so long? Should it be taking this long..
Remote SMTP is not really a good thing to use during page submissions - it's often very slow (sometimes deliberately, for greetdelay checks), as you're seeing. The way around it is to always submit to a local (fast) mail server and let it deal with the waiting around, and also handle things like deferred delivery which you can't handle from PHPMailer. You also need to deal with bounces correctly when going that route as you won't get immediate feedback.
That you can often get away with direct delivery doesn't mean it's a reliable approach.
To see what part of the SMTP conversation is taking a long time, set $mailer->SMTPDebug = 2; and watch the output (though don't do that on your live site!).
Don't know if PHPMailer is compulsory for you or not, but if it's not I am recommanding SwiftMailer .
as per my personal Experience It's Really fast and reliable.
Thanks.
include_once "inc/swift_required.php";
$subject = 'Hello from Jeet Patel, PHP!'; //this will Subject
$from = array('jeet#mydomain.com' =>'mydomain.com'); //you can use variable
$text = "This is TEXT PART";
$html = "<em>This IS <strong>HTML</strong></em>";
$transport = Swift_SmtpTransport::newInstance('abc.xyz.com', 465, 'ssl');
$transport->setUsername('MYUSERNAME#MYDOMAIN.COM');
$transport->setPassword('*********');
$swift = Swift_Mailer::newInstance($transport);
$to = array($row['email'] => $row['cname']);
$message = new Swift_Message($subject);
$message->setFrom($from);
$message->setBody($html, 'text/html');
$message->setTo($to);
$message->addPart($text, 'text/plain');
if ($swift->send($message, $failures))
{
echo "Send successfulllyy";
} else {
print_r($failures);
}
So I am using the PHPMailer library in PHP to send a welcome email when ever my users registered, and it takes so long to do this.
It takes around 30 - 50 seconds to actually load the home page, after clicking submit on the registration. It basically puts the page in a reloading state for over 30 seconds.
The code I use is below...
if ($config['user']['welcome_email_enabled'])
$autoLoader->getLibrary('mail')->sendWelcomeEmail($email, $username);
And my mail library is here.
<?php
/**
* MangoCMS, content management system.
*
* #info Handles the mail functions.
* #author Liam Digital <liamatzubbo#outlook.com>
* #version 1.0 BETA
* #package MangoCMS_Master
*
*/
defined("CAN_VIEW") or die('You do not have permission to view this file.');
class mangoMail {
private $phpMailer;
public function assignMailer($phpMailer) {
$this->phpMailer = $phpMailer;
}
public function setupMail($username, $password, $eHost) {
if ($this->phpMailer == null)
return;
$this->phpMailer->isSMTP();
$this->phpMailer->Host = $eHost;
$this->phpMailer->SMTPAuth = true;
$this->phpMailer->Username = $username;
$this->phpMailer->Password = $password;
$this->phpMailer->SMTPSecure = 'tls';
$this->phpMailer->Port = 587;
}
public function sendMail() {
if ($this->phpMailer == null)
return;
if (!$this->phpMailer->send()) {
echo 'Message could not be sent.';
echo 'Mailer Error: ' . $this->phpMailer->ErrorInfo;
exit();
}
else {
echo 'Email has been sent.';
}
}
public function setFrom($from, $fromTitle) {
$this->phpMailer->setFrom($from, $fromTitle);
}
public function addAddress($address) {
$this->phpMailer->addAddress($address);
}
public function setSubject($subject) {
$this->phpMailer->Subject = $subject;
}
public function setBody($body) {
$this->phpMailer->Body = $body;
}
public function setAltBody($altBody) {
$this->phpMailer->AltBody = $altBody;
}
public function setHTML($html) {
$this->phpMailer->isHTML($html);
}
public function addReply($email, $name = '') {
$this->phpMailer->addReplyTo($email, $name);
}
public function sendWelcomeEmail($email, $username) {
global $config;
$mailer = $this->phpMailer;
$mailer->setFrom($config['website']['email'], $config['website']['owner']);
$mailer->addAddress($email, $username);
$mailer->addReplyTo($config['website']['email'], 'Reply Here');
$mailer->isHTML(true);
$mailer->Subject = 'Welcome to ' . $config['website']['name'] . ' (' . $config['website']['link'] . ')';
$mailer->Body = '<div style="background-color:#1a8cff;padding:24px;color:#fff;border-radius:3px;">
<h2>Welcome to Zubbo ' . $username . '!</h2>Thank you for joining the Zubbo community, we offer spectacular events, opportunities, and entertainment.<br><br>When you join Zubbo you will recieve <b>250,000 credits</b>, <b>100,000 duckets</b>, and <b>5 diamonds</b>. One way to earn more is by being online and active, the more you are active the more you will earn, other ways are competitions, events, and games :)<br><br>We strive to keep the community safe and secure, so if you have any questions or concerns or have found a bug please reply to this email or contact us using in-game support.<br><br>Thank you for joining Zubbo Hotel!<br>- Zubbo Staff Team
</div>';
$mailer->AltBody = 'Here is a alt body...';
if (!$mailer->send()) {
exit('FAILED TO SEND WELCOME EMAIL!! ' . $mailer->ErrorInfo);
}
}
}
?>
So I call these to start with, then the sendWelcomeEmail() when I want to actually send the email.
$mailer->assignMailer(new PHPMailer());
and
$mailer->setupMail(
"********#gmail.com",
"**************",
"smtp.gmail.com");
Why is it taking so long? Should it be taking this long..
Remote SMTP is not really a good thing to use during page submissions - it's often very slow (sometimes deliberately, for greetdelay checks), as you're seeing. The way around it is to always submit to a local (fast) mail server and let it deal with the waiting around, and also handle things like deferred delivery which you can't handle from PHPMailer. You also need to deal with bounces correctly when going that route as you won't get immediate feedback.
That you can often get away with direct delivery doesn't mean it's a reliable approach.
To see what part of the SMTP conversation is taking a long time, set $mailer->SMTPDebug = 2; and watch the output (though don't do that on your live site!).
Don't know if PHPMailer is compulsory for you or not, but if it's not I am recommanding SwiftMailer .
as per my personal Experience It's Really fast and reliable.
Thanks.
include_once "inc/swift_required.php";
$subject = 'Hello from Jeet Patel, PHP!'; //this will Subject
$from = array('jeet#mydomain.com' =>'mydomain.com'); //you can use variable
$text = "This is TEXT PART";
$html = "<em>This IS <strong>HTML</strong></em>";
$transport = Swift_SmtpTransport::newInstance('abc.xyz.com', 465, 'ssl');
$transport->setUsername('MYUSERNAME#MYDOMAIN.COM');
$transport->setPassword('*********');
$swift = Swift_Mailer::newInstance($transport);
$to = array($row['email'] => $row['cname']);
$message = new Swift_Message($subject);
$message->setFrom($from);
$message->setBody($html, 'text/html');
$message->setTo($to);
$message->addPart($text, 'text/plain');
if ($swift->send($message, $failures))
{
echo "Send successfulllyy";
} else {
print_r($failures);
}