ArchStanton's avatar

sending email to 1000's of reciepents

Hi,

I have an email view and a list of about 1000 potential recipients. I would like to know most robust way to send am email to them all.

1 - Bcc each of them in via a loop. Send a single email to multiple recipeints.

  1. loop through and send one by one., using mail queue?

3 - mailchimp or another service

Thanks,

0 likes
19 replies
ericlbarnes's avatar

One thousand is not a lot, but here are some options:

  • Use Mandrill or Mailgun and send them in batches.
  • Use a service like Mailchimp, Campaign Monitor, or Sendy if you want to host your own system.
1 like
jekinney's avatar

If you need to consistently send that amount of emails and don't want to batch them over a few hours you'll need your own service. The mentioned services throttle the amounts per hour plus a good possibility that your email will end up in the spam folder. Many ISPs offer this as a service but if your emails get flagged they will drop you. Of course you can set up your own service too, but your IP address may get flagged over time. Which case you'll have to get a new one.

1 like
opheliadesign's avatar

Personally, I had horrible luck with Mandrill's deliverability. Their logs would show a message as Delivered, recipients swore they never received them - not in spam or anywhere else. However, @jekinney makes a very good point about sending to thousands of recipients.

I've been using Mailgun for a while now and find them to be rock solid. Very recently I switched to using their API directly rather than using Laravel's built in Mail, it opened a lot of doors such as batch sending (I had previously been putting everyone in a BCC) and recipient variables, accessible within the HTML of the email.

I have also been inlining CSS in my mail, so I have a master Blade template that I inject other email templates into, then pass through an inline script that returns HTML which can be sent using the Mailgun API.

Here is part of a class that sends out batch emails:

/**
     * 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
        ]);
    }

And here is my email inliner:

<?php namespace App\Library;

use TijsVerkoyen\CssToInlineStyles\CssToInlineStyles;

/**
 * Class inlineEmail
 *
 * Returns rendered Email view with inlined CSS
 * @package App\Library
 */
class InlineEmail {
    /**
     * Filename of the view to render
     * @var string
     */
    private $view;
    /**
     * Data - passed to view
     * @var array
     */
    private $data;

    /**
     * @param string $view Filename/path of view to render
     * @param array $data Data of email
     */
    public function __construct($view, array $data)
    {
        // Render the email view
        $emailView = view($view, $data)->render();
        $this->view = $emailView;
        $this->data = $data;
    }

    /**
     * Convert to inlined CSS
     *
     * @return string
     * @throws \TijsVerkoyen\CssToInlineStyles\Exception
     */
    public function convert()
    {
        $converter = new CssToInlineStyles();
        $converter->setUseInlineStylesBlock();
        $converter->setCleanup();
        $converter->setStripOriginalStyleTags();
        $converter->setHTML($this->view);
        $content =  $converter->convert();

        return $content;
    }
}
jekinney's avatar

@opheliadesign unfortunately I did development and design for email marketing for a few years. I say unfortunately because I hated it.

Any case there is a website I'll link when I get home that compiles your CSS and html into an email ready format that has proven to work exceptionally well across all email clients that I used. That way you can design your email just like a webpage and it adds the inline styles and tables (yes have to use tables for layout still for non web based clients like office).

opheliadesign's avatar

@jekinney I've used Premailer (http://premailer.dialect.ca/), if that's what you're thinking of. The issue is that I have about a dozen email templates that I want to use the same overall layout and each can change often. The class I posted does pretty much the exact same thing but it doesn't require hardcoding the compiled inlined CSS.

Here's the base template I'm using, for the life of me I cannot recall where I found it (it's Bootstrap for Email), haven't had any complaints from a few hundred recipients that have been receiving it for the past six or so months. I'd give credit to its author if they had included their details in the comments..

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta name="viewport" content="width=device-width"/>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <title>Email Title</title>
    <style type="text/css">
        * {
            margin: 0;
            padding: 0;
            font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif;
            font-size: 100%;
            line-height: 1.6;
        }

        img {
            max-width: 100%;
        }

        body {
            background-color: #e4e4e4;
            -webkit-font-smoothing: antialiased;
            -webkit-text-size-adjust: none;
            width: 100% !important;
            height: 100%;
        }

        a {
            color: #348eda;
        }

        .btn-primary {
            text-decoration: none;
            color: #FFF;
            background-color: #348eda;
            border: solid #348eda;
            border-width: 10px 20px;
            line-height: 2;
            font-weight: bold;
            margin-right: 10px;
            text-align: center;
            cursor: pointer;
            display: inline-block;
            border-radius: 25px;
        }

        .btn-secondary {
            text-decoration: none;
            color: #FFF;
            background-color: #aaa;
            border: solid #aaa;
            border-width: 10px 20px;
            line-height: 2;
            font-weight: bold;
            margin-right: 10px;
            text-align: center;
            cursor: pointer;
            display: inline-block;
            border-radius: 25px;
        }

        .btn-success {
            text-decoration: none;
            color: #FFF;
            background-color: #449D44;
            border: solid #449D44;
            border-width: 10px 20px;
            line-height: 2;
            font-weight: bold;
            margin-right: 10px;
            text-align: center;
            cursor: pointer;
            display: inline-block;
            border-radius: 25px;
        }

        .btn-danger {
            text-decoration: none;
            color: #FFF;
            background-color: #C9302C;
            border: solid #C9302C;
            border-width: 10px 20px;
            line-height: 2;
            font-weight: bold;
            margin-right: 10px;
            text-align: center;
            cursor: pointer;
            display: inline-block;
            border-radius: 25px;
        }

        .last {
            margin-bottom: 0;
        }

        .first {
            margin-top: 0;
        }

        .padding {
            padding: 10px 0;
        }

        table.body-wrap {
            width: 100%;
            padding: 20px;
        }

        table.body-wrap .container {
            border: 1px solid #f0f0f0;
        }

        table.footer-wrap {
            width: 100%;
            clear: both !important;
        }

        .footer-wrap .container p {
            font-size: 12px;
            color: #666;

        }

        table.footer-wrap a {
            color: #999;
        }

        h1, h2, h3 {
            font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
            line-height: 1.1;
            margin-bottom: 15px;
            color: #000;
            margin: 40px 0 10px;
            line-height: 1.2;
            font-weight: 200;
        }

        h1 {
            font-size: 36px;
        }

        h2 {
            font-size: 28px;
        }

        h3 {
            font-size: 22px;
        }

        p, ul, ol {
            margin-bottom: 10px;
            font-weight: normal;
            font-size: 14px;
        }

        ul li, ol li {
            margin-left: 5px;
            list-style-position: inside;
        }

        .container {
            display: block !important;
            max-width: 600px !important;
            margin: 0 auto !important; /* makes it centered */
            clear: both !important;
        }

        .body-wrap .container {
            padding: 20px;
        }

        .content {
            max-width: 600px;
            margin: 0 auto;
            display: block;
        }

        .content table {
            width: 100%;
        }
    </style>
</head>

<body bgcolor="#f6f6f6">
<table class="body-wrap">
    <tr>
        <td></td>
        <td class="container" bgcolor="#FFFFFF">
            <div class="content">
                <table>
                    <tr>
                        <td align="center">
                            <img src="https://demo.org/images/Client-Logo.png" alt="Client"/>
                        </td>
                    </tr>
                    @yield('content')
                </table>
            </div>
        </td>
        <td></td>
    </tr>
</table>
<table class="footer-wrap">
    <tr>
        <td></td>
        <td class="container">
            <div class="content">
                <table>
                    <tr>
                        <td align="center">
                            <p>Email Footer</p>

                            <p><strong>ALL EMAILS ARE TO BE CONSIDERED CONFIDENTIAL UNLESS OTHERWISE
                                    NOTED</strong></p>
                        </td>
                    </tr>
                </table>
            </div>
        </td>
        <td></td>
    </tr>
</table>
</body>
</html>
jlrdw's avatar

If sending out that many emails are they those kind of emails at people flat out don't want anyway like advertising emails I mean what in the world are you doing?

opheliadesign's avatar

@jlrdw can't speak for the original poster but in my case I'm sending out alerts and group messages to large organizations. And believe me, they want them - there's hell to pay if they don't make it through!

2 likes
jlrdw's avatar

I never thought of that sorry.

3 likes
DMA's avatar

@opheliadesign I manage a project that sends out around 50,000 e-mails or so a week. And like you, it's generally to large organizations who are paying a substantial fee to receive our data so there are quite severe implications of our e-mails don't go out.

We've opted for using SendGrid. They're API isn't perfect, but it allows us a great deal of flexibility. I usually push around 3000 or so e-mails to them (rather a template, with a payload of recipient data, used to customize each e-mail) and they are delivered all within a few minutes.

1 like
jekinney's avatar

@opheliadesign yes, that was the link..lol.

And to also through in my 2 cents, we charged $1 usd per email with one custom template at a minimum charge of $2000 a month. And even those that where not corporate emails pay more and like old snail mail flyers, it is a marketing technique that is tracked similar to google add sense. Huge amounts of money but cheaper to farm out then do in house.

Top client was around $10000 a month. Killer is once your system is up and running, takes a few hours to set up the "blast" and money in the bank.

1 like
opheliadesign's avatar

@jekinney unfortunately I mostly deal with non-profits and local government organizations that really cannot afford anything like that (or can get approval) :/ Someday.. ::crossing fingers::

jekinney's avatar

@opheliadesign

I hated it, manly because, with out fail. They would send a word doc as a template. Word formats images nicely but with out actually cropping the image. So complaint 1 was image looks like crap, but original image was 100px by 200px stretched to 600px wide.

Links where almost always wrong... It also seemed like they didn't proof the doc so I would get a change request with add commas here, more space there etc. Seemed like I did templates 4-5 times before I would get the go ahead. Few clients told me to pull my head out of my butt and should know what they want.

Worst was French. I don't know the language and would get a change to change a word somewhere from this to that.....

opheliadesign's avatar

@jekinney Zoiks! Most of the emails my clients need can fit into a predefined structure, such as meeting reminders, events, alerts (including static Gmaps), etc. For the free-form emails I use a WYSIWYG editor (Redactor) - works pretty well. The template I posted is responsive, haven't had any issues with it yet on mobile or desktop.

1 like
jekinney's avatar

@opheliadesign Think we highjacked this topic, but we could have a heck of a conversation I think. Your perspective (code) is very interesting. Imagine together.......

1 like
usamamashkoor's avatar

Can we use Amazon SES or Amazon SQS for sending 1000 emails in one hour...?

Please or to participate in this conversation.