Perhaps the greatest benefit of using SendGrid (besides the fact that they handle your email delivery) is that they also provide you with a web dashboard that lets you see what is happening to your mass mailings with plenty of analytics to support your efforts. They also ensure that bad email addresses or bounces are never sent again to prevent ISPs from establishing a pattern that your "from" address (your domain) is apt to sending bad emails or spam. This happens even when you generate a new mass mailer that may once again contain the culprit addresses that would go out for delivery. You don't even need to update your own database if you don't want to remove them, SendGrid will automatically skip over them to save you the hassle (though, I recommend you write some script to handle the emails they identify as bad or marked as unsubscribe since they will count the attempt to resend them against your monthly quota).

Anyhow, enough talk on my part, let's get to the good stuff. Here is how I did it in PHPR:

Step 1:
Create your free account with SendGrid.com

Step 2:
Read their API and download SwiftMailer (open-source and free).

Step 3:
Create a folder in your projects web folder called "swift" (in the root of your project folder. aka where you see classes, images, include, libs, etc)

Step 4:
Copy all of the contents inside the "lib" folder of the downloaded swift mailer folder and paste into your newly created "swift folder" (there should be 2 folders and 5 php files).

Step 5:
Create a folder in your projects web folder called "sendgrid" (in the root of your project folder. aka where you see classes, images, include, libs, etc)

Step 6:
Inside the "sendgrid" folder create the SmtpApiHeader.php" file as shown in the SendGrid developer API documentation

Step 7:
In the list page where you have the email records you want to send (this assumes that each of those list page records already contain your email data such as from, to, subject, body, etc) insert a custom button using visual editor.

Step 8
In that newly created button (I named mine "Email_Selected_Records") add the following code:

Client Before tab:
this.setEnabled(); //ensure button will work even after 1st time its clicked in case your page doesn't explicitly call for a refresh)
if (confirm    ('Are you sure you want to email selected records now?\n\rThis may take 1 to 2 minutes to complete.')) {
        ctrl
.setMessage("Emailing records... please be patient while we process your request. This can take between 60 to 120 seconds");
       
this.setDisabled();
       
} else  {
               
return;
};


Step 9:
Tweak this code as you see fit. This is a mash-up for what I found in the PHPR online manual (for looping through selected records to send email) and the API provided by sendgrid).
On Server tab:
include_once
('swift/swift_required.php');
include_once
('sendgrid/SmtpApiHeader.php');
ignore_user_abort
(true); //will run script even if user closes browser or disconnects
set_time_limit
(300);
$hdr
= new SmtpApiHeader();
//$hdr->addFilterSetting('footer', 'enable', 1);
//$hdr->addFilterSetting('footer', "text/plain", "Thank you for your business");
global $dal;
$dal_TableName
= $dal->Table("letters_sub_tbl");
$body
="";
$result
["txt"]="";
$username
= 'your_sendgrid_username';
$password
= 'your_send_grid_password';
// Create new swift connection and authenticate
$transport
= Swift_SmtpTransport::newInstance('smtp.sendgrid.net', 25);
$transport
->setUsername($username);
$transport
->setPassword($password);
$swift
= Swift_Mailer::newInstance($transport);
foreach(@$keys as $keyblock)
{
  $arr
=split("&",refine($keyblock["LettersSubID"]));
 
if(count($arr)<1)
   
continue;
  $arr2
=array();
  $arr2
["LettersSubID"]=urldecode(@$arr[0]);
  $where
= KeyWhere($arr2);
  $rstmp
= $dal_TableName->Query($where,"");
  $data
=db_fetch_array($rstmp);

       
if($data["Parent1_Email"] > '' and filter_var($data["Parent1_Email"], FILTER_VALIDATE_EMAIL)){
               
//Custom part not part of the online manual example
                $to
=$data["Parent1_Email"];
                $from
=$data["Email_From"];
                $subject
=$data["Letter_Subject"];              
                $text
= $data["Letter_Body"];
                $html
= "<html>".$data["Letter_Body"]."</html>";
                $hdr
->setUniqueArgs(array('from'=>$from, 'subject'=>$subject)); //MBR needed in order for mbr_sendgrid_bounce_action.php receiver page to capture "from" and "subject" so we can route bounce to correct person
                $hdr
->setCategory($from); //we want to categorize based on from email so we know which schools are sending which batches in sendgrid.
               
// Create a message (subject)
                $message
= new Swift_Message($subject);
               
// add SMTPAPI header to the message
                $headers
= $message->getHeaders();
                $headers
->addTextHeader('X-SMTPAPI', $hdr->asJSON());
               
// attach the body of the email
                $message
->setFrom($from);
                $message
->setBody($html, 'text/html');
                $message
->setTo($to);
                $message
->addPart($text, 'text/plain');
               
// send message
               
if ($recipients = $swift->send($message, $failures))
               
{
                $t
= microtime(true); //http://php.net/manual/en/function.date.php
                $micro
= sprintf("%06d",($t - floor($t)) * 1000000);
                $d
= new DateTime( date('Y-m-d H:i:s.'.$micro,$t) );
                $sql
= "UPDATE letters_sub_tbl SET Microseconds = '".$d->format("Y-m-d H:i:s.u")."',Emailed_On = now()WHERE LettersSubID = '" . $data["LettersSubID"]."'";
               
CustomQuery($sql);
               
}else{
               
//echo "Something went wrong - ";
               
//print_r($failures);
               
//$result["EmailsSent"] = 0;
                $result
["txt"] = print_r($failures);
               
}
       
}
       
if($data["Parent2_Email"] > '' AND filter_var($data["Parent2_Email"], FILTER_VALIDATE_EMAIL)){
               
//Custom part not part of the online manual example
                $to
=$data["Parent2_Email"];
                $from
=$data["Email_From"];
                $subject
=$data["Letter_Subject"];              
                $text
= $data["Letter_Body"];
                $html
= "<html>".$data["Letter_Body"]."</html>";
                $hdr
->setUniqueArgs(array('from'=>$from, 'subject'=>$subject)); //needed in order for mbr_sendgrid_bounce_action.php receiver page to capture "from" and "subject" so we can route bounce to correct person
                $hdr
->setCategory($from); //we want to categorize based on from email so we know which schools are sending which batches in sendgrid.
               
// Create a message (subject)
                $message
= new Swift_Message($subject);
               
// add SMTPAPI header to the message
                $headers
= $message->getHeaders();
                $headers
->addTextHeader('X-SMTPAPI', $hdr->asJSON());
               
// attach the body of the email
                $message
->setFrom($from);
                $message
->setBody($html, 'text/html');
                $message
->setTo($to);
                $message
->addPart($text, 'text/plain');
               
// send message
               
if ($recipients = $swift->send($message, $failures))
               
{
                $t
= microtime(true);//http://php.net/manual/en/function.date.php
                $micro
= sprintf("%06d",($t - floor($t)) * 1000000);
                $d
= new DateTime( date('Y-m-d H:i:s.'.$micro,$t) );
                $sql
= "UPDATE letters_sub_tbl SET Microseconds = '".$d->format("Y-m-d H:i:s.u")."',Emailed_On = now() WHERE LettersSubID = '" . $data["LettersSubID"]."'";
               
CustomQuery($sql);
               
}else{
               
//echo "Something went wrong - ";
               
//print_r($failures);
               
//$result["EmailsSent"] = 0;
                $result
["txt"] = print_r($failures);
               
}
       
}
}


Step 10:
Provide feedback message to users!
var message = result["txt"];
ctrl
.setMessage(message);    
alert
('Emails were sent successfully. Page will now reload.');
window
.location.reload();


Done, now you have a button that sends emails using SendGrid's service... you can then login to your account and monitor all email activity and even include their apps for enhanced functionality without adding any more code (although, you may have to tweak some parameters in the On Server tab in step 9 to handle things like category, footer, etc).

Note: sending email via sendgrid actually uses their servers, however the email from shown to recipients will be the from address you provide. In some instances, it may show to recipient as "sent on behalf of' instead of your actual domain. SendGrid has a "whitelabel" wizard that allows you to update your mx records so that the email will always show as coming from your domain. I opted to forgo that since it seems that the "sent on behalf messages" occurs very infrequently.

I hope this helps others... and no, I am not affiliated with SendGrid in any way, shape, or form. I am simply a thankful customer of theirs, who appreciates the amount of time they saved me in solving my mass emailing issues.

Cheers,

Post a Comment