Sending large amounts of emails using PHP Mailer with CodeIgniter 3 - php

I need help sending large amounts of emails through my newly designed automated email platform.
I am using PHP Mailer Library to send emails to my contacts
I built my script in CodeIgniter 3
I am using VPS level 3 from Godaddy
My email system freezes after 5 or more emails in mail queue manager
I am assuming that my script is designed for large volumes of emails.
Mail queue manager in Godaddy WHM panel shows all my emails as FROZEN
Part of my script:
$options = [
'user_id' => $this->me->id,
'limit' => 200000,
'type' => $exploded[1]
];
$this->data['contacts'] = $this->crm_model->get_portal_contacts($options);
$emails = array();
foreach ($this->data['contacts'] as $contact) {
$this->data['fullname'] = get_user($contact)->full_name(false);
$emaildata = [
'from' => ['name' => 'Domain', 'email' => '<no-reply#domai.org>\r\n'],
'to' => strip_tags(get_user($contact)->email),
'subject' => $this->data['email']['email_subject'],
'message' => $this->load->view('np_sh/email/email-template', $this->data, TRUE)
];
$status = _send_mail($emaildata);
}
_send_mail() function is merging $emaildata variable with the default parameters and preparing to send email using PHPMailer and returning boolean status.

Related

AWS SES SMTP email works. AWS SES API does not send email

I am using AWS SES on a website with shared hosting platform (not on AWS)
When I send emails using the SMTP it works perfectly. When I attempt to call and use the API, no email is sent, no error message is received.
There are two reasons I want to use the API instead of SMTP
1) According to Amazon, the API is faster.
2) One of my transactional emails is a reminder to clients to log in, and/or pay their account. SMTP cannot send email to more than 50 (if I am not mistaken). For that reason, I need to call the SendRawEmail.
Please help me with my code to send the email and to implement SendRawEmail
Here is my code:
require ('PHPMailer/PHPMailerAutoload.php');
use Aws\Ses\SesClient;
use Aws\Exception\AwsException;
// Create an SesClient. Change the value of the region parameter if you're
// using an AWS Region other than US West (Oregon). Change the value of the
// profile parameter if you want to use a profile in your credentials file
// other than the default.
$SesClient = new SesClient([
'profile' => 'default',
'version' => '2010-12-01',
'region' => 'eu-central-1'
]);
// Replace sender#example.com with your "From" address.
// This address must be verified with Amazon SES.
$sender_email = 'info#mydomain.com';
// Replace these sample addresses with the addresses of your recipients. If
// your account is still in the sandbox, these addresses must be verified.
$recipient_emails = ['info#example.com'];
// Specify a configuration set. If you do not want to use a configuration
// set, comment the following variable, and the
// 'ConfigurationSetName' => $configuration_set argument below.
//$configuration_set = 'ConfigSet';
$subject = 'Amazon SES test (AWS SDK for PHP)';
$plaintext_body = 'This email was sent with Amazon SES using the AWS SDK for PHP.' ;
$html_body = '<h1>AWS Amazon Simple Email Service Test Email</h1>'.
'<p>This email was sent with <a href="https://aws.amazon.com/ses/">'.
'Amazon SES</a> using the <a href="https://aws.amazon.com/sdk-for-php/">'.
'AWS SDK for PHP</a>.</p>';
$char_set = 'UTF-8';
try {
$result = $SesClient->sendEmail([
'Destination' => [
'ToAddresses' => $recipient_emails,
],
'ReplyToAddresses' => [$sender_email],
'Source' => $sender_email,
'Message' => [
'Body' => [
'Html' => [
'Charset' => $char_set,
'Data' => $html_body,
],
'Text' => [
'Charset' => $char_set,
'Data' => $plaintext_body,
],
],
'Subject' => [
'Charset' => $char_set,
'Data' => $subject,
],
],
// If you aren't using a configuration set, comment or delete the
// following line
'ConfigurationSetName' => $configuration_set,
]);
$messageId = $result['MessageId'];
echo("Email sent! Message ID: $messageId"."\n");
} catch (AwsException $e) {
// output error message if fails
echo $e->getMessage();
echo("The email was not sent. Error message: ".$e->getAwsErrorMessage()."\n");
echo "\n";
}
?>
Check your error log. I had the same issue:
require 'AWS/aws-autoloader.php';
For other SDK uses (such as API calls) you may need to create a .aws folder to include credentials

Class 'Swift_Mime_Headers_UnstructuredHeader' not found in Laravel 5.4

I am sending e-mails from Laravel app, the e-mail is working fine in localhost, but not working in production server.
Note: Hosted the application in Shared Hosting (as its for personal use)
My Controller
public function createapplication(Request $request)
{
$leaves = Application::create([
'emp_id' => auth()->user()->id,
'from_date' => request('from_date'),
'to_date' => request('to_date'),
'days' => request('days'),
'reason' => request('reason')
]);
$fromdate = $request->from_date;
$to_date = $request->to_date;
$days = $request->days;
$reason = $request->reason;
$data = array(
'name' => auth()->user()->name,
'From_date' => $fromdate,
'To_date' => $to_date,
'Days' => $days,
'Reason' => $reason
);
Mail::send('mail.leavesmail', $data, function($message) use ($fromdate, $to_date, $days, $reason)
{
$message->to('example.com', 'example')->subject('Leave Application');
$message->from('example.com', "example");
$message->cc(auth()->user()->email);
});
return redirect()->back()->with('status', 'Leave Application Submitted Successfully!');
}
For personal use or not, using your own host to send mail is generally a bad idea. There are many problems that you may come across from not being able to send mail (Host disables mail sending to stop spam). Mail going into spam (Mail comes from a known spam IP) among other issues. For this reason I would suggest Mailgun, it's free tier will keep you going forever.
Onto the problem itself, have you run composer install it looks as if a class is just missing due to that?

How to use AWS SDK for PHP to send email by SES with dedicated IP?

My aws/aws-sdk-php version is 2.7.27. The emails we sent are marked as spam. I found that my AWS account has got 8 dedicated IPs in Dedicated IPs page. But the sender IP of my email isn't any of the dedicated IPs, it's a shared IP of amazon SES. In developer document of SES, I found that they said I can make a Configuration Set to specify whick IP pool is used for sending. I add a param called 'ConfigurationSetName' as the doc said but it doesn't work, my emails are still sending through shared IPs. My code is like:
$sendingParams = array(
'Source' => $fromEmail,
'Destination' => array(
'ToAddresses' => is_array($email) ? $email : array($email),
//'CcAddresses' => is_array($ccEmail) ? $ccEmail : array($ccEmail),
//'BccAddresses' => is_array($bccEmail) ? $bccEmail : array($bccEmail),
),
'Message' => array(
// Subject is required
'Subject' => array(
// Data is required
'Data' => $subject,
'Charset' => 'utf-8',
),
// Body is required
'Body' => array(
'Html' => array(
// Data is required
'Data' => $content,
'Charset' => 'utf-8',
),
),
),
'ReplyToAddresses' => array($fromEmail),
'ReturnPath' => $returnPath,
'ConfigurationSetName' => 'system',
);
if (!empty($ccEmail)) {
$sendingParams['Destination']['CcAddresses'] = is_array($ccEmail) ? $ccEmail : array($ccEmail);
}
if (!empty($bccEmail)) {
$sendingParams['Destination']['BccAddresses'] = is_array($bccEmail) ? $bccEmail : array($bccEmail);
}
$result = $this->sdkClient->sendEmail($sendingParams);
What's the problem with my code? Should I change the version of the SDK?
I find the problem. My dedicated IPs are warming up, and I can't use them before they were totally warmed up.

send email by Mandrill

I need to send an email for mandrill. This Mandrill API implemented in my project, and send a test mail by apikey provided by the client. I have two options for sending mail, one is by my account of Mandrill and the other is that the user can login by MailChimp. Then insert the API KEY mandrill your account.
I have a default variable in conf file like this:
public $default = array(
'transport' => 'Smtp',
'from' => array('noreply#example.com' => 'Example'),
'host' => 'smtp.mandrillapp.com',
'port' => 587,
'timeout' => 30,
'username' => 'example#example.com',
'password' => '12345678',
'client' => null,
'log' => false
//'charset' => 'utf-8',
//'headerCharset' => 'utf-8',
);
To send mail through my account mandrill I do this:
$email = new FrameworkEmail();
$email->config('default');
$email->emailFormat('html');
And I give my account Mandrill data. But if the user chooses to identify with MailChimp and also add your API KEY Mandrill mails should be sent from your account transactional emails and not mine. Any idea if this is possible?
I do not believe this is possible to authenticate with MailChimp and then send through Mandrill. The Mandrill API uses a different set of keys than the MailChimp API, so you won't have access to a user's Mandrill API keys if they're logged in through MailChimp.
EDIT: If you have a user's Mandrill API key, you should be able to feed it directly into the Mandrill send function from the Mandrill SDK:
<?php
$mandrill = new Mandrill('USER_PROVIDED_API_KEY_GOES_HERE');
$message = array(
'html' => '<p>html content here</p>',
// other details here
)
$async = False;
$ip_pool = null;
$send_at = null;
$result = $mandrill->messages->send($message, $async, $ip_pool, $send_at);
?>
More details on the Message function in the SDK can be found here.
EDIT #2: Same approach can be achieved using CakeEmail - you just need to instantiate the $email class at the time that you receive the user's API key, rather than before.
CakeEmail recommends in a standard setup that you do this in your initial configuration:
class EmailConfig {
public $mandrill = array(
'transport' => 'Mandrill.Mandrill',
'from' => 'from#example.com',
'fromName' => 'FromName',
'timeout' => 30,
'api_key' => 'YOUR_API_KEY',
'emailFormat' => 'both',
);
}
But we can't set this up with default values and then change it per user, using their API key. We need to instantiate this at the time that we receive the user's email, like so:
App::uses('CakeEmail', 'Network/Email');
// PHP code that takes in user email
$user_api_key = // this would come from a form, or from a user's record in the database
$email = new CakeEmail(array(
'transport' => 'Mandrill.Mandrill',
'from' => 'from#example.com',
'fromName' => 'FromName',
'timeout' => 30,
'api_key' => $user_api_key,
'emailFormat' => 'both',
));
// add CakeEmail details like $email->template, $email->subject(), etc.
$email->send();
So the principles are the same regardless of what framework is used. Rather than instantiating Mandrill configuration details in a global setting (like most email frameworks recommend), you will need to instantiate them at the time the user wants to send an email, using user-specific details.

Laravel: How to Queue mails to send later

Im trying to use the Mail::queue to send and email, but when I call this function it simple sends the mail, and the response is delayed ... I thought that the point of using Mail::queue was to queue ....
I want the response to came instantly, not having to wait for the email to be sent
for eg
Mail::queue('emails.template', $data, function($message) {
$message->to('somemail#gmail.com');
$message->subject('Notificacion');
});
return Response::json(array('error' => 0, 'message' => 'Ok'));
I want to receive the response without waiting for the mail to be sent.
How can I do that???
What queue driver (app/config/queue.php - 'default' param) are you using? If you're using sync, and haven't set up one of the others, then you're using the synchronous driver, which does exactly what the name says: Runs your queued task as soon as the task is created.
You need to configure an MQ server for Laravel to talk to. You can get a free iron.io account for this, and then you need to configure it, for instance:
'iron' => array(
'driver' => 'iron',
'project' => 'iron-io-project-id',
'token' => 'iron-io-queue-token',
'queue' => 'queue-name',
),
Then when you use Mail::queue() it will push the instruction to iron.io. You'll then have to have another thread listening on the queue - just run php artisan queue:listen and leave it running while messages are pushed to the queue.
/**
* Get all email recipients and include their user details for Mailgun's
* template tags - %recipient.userToken%
*/
private function getRecipients()
{
foreach (User::get() as $user)
{
$this->recipients[$user->email] = [
'id' => $user->id,
'userToken' => $user->user_token,
'first_name' => $user->first_name,
'last_name' => $user->last_name,
'email' => $user->email
];
}
}
private function sendEmail()
{
$subject = 'Demo Subject';
/**
* Data for the Blade template
*/
$data = [
'foo' => 'bar'
];
// Inline the CSS for the email
$inliner = new InlineEmail('emails.some-email', $data);
$content = $inliner->convert();
// Create Emails table entry for this email. Used for Mailgun webhooks
$email = Email::create(['user_id' => $this->userId, 'subject' => $subject, 'email_id' => str_random()]);
// Prepare the email addresses
$emailAddresses = array_column($this->recipients, 'email');
$this->mailgun->sendMessage('demo.org', [
"from" => 'support#demo.org',
"to" => implode(',', $emailAddresses), // Comma separated list of email addresses
"subject" => $subject,
"html" => $content, // Inlined CSS HTML from Blade
"text" => "Plain text message here",
"recipient-variables" => json_encode($this->recipients), // Required for batch sending, matches to recipient details
"v:messageId" => $email->id, // Custom variable used for webhooks
]);
}

Categories