Reputation: 1228
Is there a way to send a self-designed HTML and CSS email to a Mailchimp List from a .php page? I want to integrate a newsletter function to an admin panel with my own newsletter template and send it from there.
I don't wanna have to log in to Mailchimp every time I wanna send an email, especially since the template will be the same each and every time.
Upvotes: 17
Views: 8567
Reputation: 7409
Your question is split up into two chunks:
The first chunk is the most important here. The second chunk has a ton of possible answers and should be fairly easy to accomplish.
Getting the list from MailChimp
MailChimp provides an API that is critical. Currently, they are working on v3.0, but v2.0 is still marked as 'current', so we will be relying on that version of the API. To use the API, MailChimp recommends a few third-party packages. For this example, I am using mailchimp-api which can be installed using composer:
$ composer require drewm/mailchimp-api
To authenticate yourself to MailChimp, you will need an API key. MailChimp provides full instructions to get the API key, but the short version is this:
Click your profile name to expand the Account Panel, and choose Account.
Click the Extras drop-down menu and choose API keys.
Copy an existing API key or click the Create A Key button.
Name your key descriptively, so you know what application uses that key.
Next, you need your list id for the list you want to grab emails from. Once again, MailChimp provides the best documentation for this. My list id was a string of 10 characters containing both letters and numbers.
Finally, we write the PHP:
$apiKey = /*Your API key*/;
$listId = /*Your List ID*/;
$MailChimp = new \Drewm\MailChimp($apiKey);
$args = array(
'id' => $listId,
);
$result = $MailChimp->call('lists/members', $args);
//Check for any errors first, if none have occured, build the email list.
if(isset($result['status']) && $result['status'] == 'error'){
throw new Exception('call to Mailchimp API has failed.');
} else {
$emails = array();
//Build an array of emails for users that are currently subscribed.
foreach($result['data'] as $recipient){
if($recipient['status'] == 'subscribed' && !empty($recipient['email'])){
$emails[] = $recipient['email'];
}
}
}
$MailChimp->call('lists/members', $args)
returns a very hefty JSON response with lots of interesting information. If you were storing personalized information via merge settings in MailChimp, they will be available in this JSON response. However, to keep this example as simple as possible, I've only checked if a user is subscribed and stored their email address.
At the end of this block, $emails
now store all of the email address in your list. Since this calls the API each time, anyone who unsubscribes from your mailing list on MailChimp will be removed here as well.
A possible gotcha may occur during this stage. If you have a large list (I tested with only 4), you may run into a memory issue where PHP tries to build a huge $emails
array. If you run into this problem, you should chunk out reading emails in smaller blocks and send emails like that.
Sending bulk email using PHP
Others have recommended using Mandrill to send out bulk email. This is bad idea. Mandrill is the sister service to MailChimp that is intended to send out transactional email - MailChimp is intended for bulk email (like a newsletter).
There are tons of ways to send out emails using PHP, I'm opting to use Sendgrid as my SMTP provider and SwiftMailer to connect to it. Other alternatives would be to use PHP's mail()
function or a different library like PHPMailer.
You can install SwiftMailer using Composer:
$ composer require swiftmailer/swiftmailer @stable
I go into more detail about SwiftMailer and SMTP services (though in slightly different context) in this question. But this example will do what it needs to.
$sendgridUser = /*SendGridUsername*/;
$sendgridPassword = /*SendGridPassword*/;
$subject = "Thank you for using MailChimp Lists!";
$fromAddress = "[email protected]";
$fromName = "Hayden Pierce";
$body = file_get_contents(/*path to content (body.html)*/);
$transport = Swift_SmtpTransport::newInstance('smtp.sendgrid.net', 587, 'tls')
->setUsername($sendgridUser)
->setPassword($sendgridPassword)
;
foreach($emails as $email){
$mailer = Swift_Mailer::newInstance($transport);
$message = Swift_Message::newInstance()
->setSubject($subject)
->setFrom(array($fromAddress => $fromName))
->setTo($email)
->setBody($body);
$mailer->send($message);
exit();
}
For simplicity's sake, I've read the entire body from a static HTML file. You may consider using a template engine like Twig to better implement it using templates.
All this code put together looks like this:
//Loading in composer dependencies
require "vendor/autoload.php";
//Provided by Mailchimp account settings
$apiKey = /*MailChimp API keys*/;
$listId = /*MailChimp List id*/;
$sendgridUser = /*SendGridUser*/;
$sendgridPassword = /*SendGridPassword*/;
$subject = /*The subject line of your email*/;
$fromAddress = /*The email address for your FROM line*/;
$fromName = /*The name in your FROM line*/;
$body = file_get_contents(/*path to your html content*/);
$MailChimp = new \Drewm\MailChimp($apiKey);
$args = array(
'id' => $listId,
);
$result = $MailChimp->call('lists/members', $args);
//Check for any errors first, if none have occurred, build the email list.
if(isset($result['status']) && $result['status'] == 'error'){
throw new Exception('call to Mailchimp API has failed.');
} else {
$emails = array();
//Build an array of emails for users that are currently subscribed.
foreach($result['data'] as $recipient){
if($recipient['status'] == 'subscribed' && !empty($recipient['email'])){
$emails[] = $recipient['email'];
}
}
}
//Setup for sending emails to an arbitrary list of emails using Sendgrid.
$transport = Swift_SmtpTransport::newInstance('smtp.sendgrid.net', 587, 'tls')
->setUsername($sendgridUser)
->setPassword($sendgridPassword)
;
foreach($emails as $email){
//Send emails to each user.
$mailer = Swift_Mailer::newInstance($transport);
$message = Swift_Message::newInstance()
->setSubject($subject)
->setFrom(array($fromAddress => $fromName))
->setTo($email)
->setBody($body);
$mailer->send($message);
}
Upvotes: 1
Reputation: 567
To create a campaign with custom HTML
Use campaigns/create api endpoint: https://apidocs.mailchimp.com/api/2.0/campaigns/create.php
PHP wrapper is here: https://bitbucket.org/mailchimp/mailchimp-api-php
It seems that Mailchimp_Campaigns::create is the function you can use. Pay close attention to $content parameter (html string for raw/pasted HTML content)
Once the campaign is created, you'll get it's ID.
To send the created campaign
Use function Mailchimp_Campaigns::send with the ID of the previously created campaign
Upvotes: 0
Reputation: 369
If you don't want to upload your template to Mailchimp and send a campaign by hitting their API, Mandrill (as @Whymarrh mentioned above in the comments) may be a good option.
Although it's meant for transactional emails (welcome, password recovery, etc), you can send to up to 1000 users at a time through SMTP. Plus you can connect your Mailchimp account to your Mandrill one in the Integrations section to track recipient activity.
My suggestion would be to install the Mandrill PHP API client, upload your template to Mandrill, hit the Mailchimp API for your user list, and then feed that into a Mandrill send-template call that you trigger through your admin panel. (Pro tip on sending mass emails: Mandrill sending to multiple people as separate message via the REST API).
Upvotes: 2
Reputation: 4643
v2.0 (deprecated) of the MailChimp API has Campaign Creation and Campaign Send methods. These are not the easiest methods to use, but the current API (v3.0) doesn't have them yet, so that's your best option.
Upvotes: 0
Reputation: 3027
Yes, you can. The details and examples from MailChimp are available by logging in to their control panel. Use their form fields, style your own form.
<form action='http://xxxx.xxxxlist-manage.com/subscribe' method='post'>
<p><input type="email" value="" name="EMAIL" class="required email" id="mce-EMAIL" placeholder="enter email address"></p>
<p><input type="submit" value="Sign Up" name="subscribe" id="mc-embedded-subscribe" class="btn"></p>
<input type='hidden' name='u' value='xxxxxxx'>
<input type='hidden' name='id' value='xxxxxxx'>
</form>
Upvotes: 2