datasn.io
datasn.io

Reputation: 12867

PHP mail() messages not received by user / customer?

This is my in-house Email class that uses the PHP mail() to deliver emails:

class Email {

    public $from = '';
    public $from_name = '';
    public $reply_to = '';
    private $to = '';
    private $subject = '';
    private $message = '';
    private $attachment = '';
    private $attachment_filename = '';

    public function __construct($to, $subject, $message, $attachment = '', $attachment_filename = '') {
        $this -> to = $to;
        $this -> subject = $subject;
        $this -> message = $message;
        $this -> attachment = $attachment;
        $this -> attachment_filename = $attachment_filename;

        $this -> from = SITE_EMAIL;
        $this -> from_name = SITE_NAME_URL;
        $this -> reply_to = SITE_EMAIL;
    }

    public function mail() {

        if (!empty($this -> attachment)) {
            $filename = empty($this -> attachment_filename) ? basename($this -> attachment) : $this -> attachment_filename ;
            $path = dirname($this -> attachment);
            $mailto = $this -> to;
            $from_mail = $this -> from;
            $from_name = $this -> from_name;
            $replyto = $this -> reply_to;
            $subject = $this -> subject;
            $message = $this -> message;

            $file = $path.'/'.$filename;
            $file_size = filesize($file);
            $handle = fopen($file, "r");
            $content = fread($handle, $file_size);
            fclose($handle);
            $content = chunk_split(base64_encode($content));
            $uid = md5(uniqid(time()));
            $name = basename($file);
            $header = "From: ".$from_name." <".$from_mail.">\r\n";
            $header .= "Reply-To: ".$replyto."\r\n";
            $header .= "MIME-Version: 1.0\r\n";
            $header .= "Content-Type: multipart/mixed; boundary=\"".$uid."\"\r\n\r\n";
            $header .= "This is a multi-part message in MIME format.\r\n";
            $header .= "--".$uid."\r\n";
            $header .= "Content-type:text/plain; charset=iso-8859-1\r\n";
            $header .= "Content-Transfer-Encoding: 7bit\r\n\r\n";
            $header .= $message."\r\n\r\n";
            $header .= "--".$uid."\r\n";
            $header .= "Content-Type: application/octet-stream; name=\"".$filename."\"\r\n"; // use diff. tyoes here 
            $header .= "Content-Transfer-Encoding: base64\r\n";
            $header .= "Content-Disposition: attachment; filename=\"".$filename."\"\r\n\r\n";
            $header .= $content."\r\n\r\n";
            $header .= "--".$uid."--";
            if (mail($mailto, $subject, "", $header, '-f'.$this -> from)) {
                return true;
            } else {
                return false;
            }
        } else {
            $header = "From: ".($this -> from_name)." <".($this -> from).">\r\n";
            $header .= "Reply-To: ".($this -> reply_to);
            if (mail($this -> to, $this -> subject, $this -> message, $header, '-f'.$this -> from)) {
                return true;
            } else {
                return false;
            }
        }

    }   

}

Every time a user completes order and pays via PayPal with IPN status = "Completed", IPN notifies my site and this function is triggered:

function emailBuyerAdminCompleted($ipn_data, $validItemsText, $password) {
    $message = "Hi, {$ipn_data['first_name']},

PayPal transaction details
-------------------------------
Buyer name: {$ipn_data['first_name']} {$ipn_data['last_name']}
Transaction ID: {$ipn_data['txn_id']}
Payment gross: {$ipn_data['mc_gross']}
Payment currency: {$ipn_data['mc_currency']}
Payment date: {$ipn_data['payment_date']}
Number of items: {$ipn_data['num_cart_items']}

Product(s) purchased
-------------------------------
$validItemsText
Authentication credentials
-------------------------------
User Name: {$ipn_data['payer_email']}
Password: $password



Regards,
".SITE_NAME." Team
".SITE_URL."/";
    $buyerEmail = new Email($ipn_data['payer_email'], 'Product(s) Download Credentials - $'.$ipn_data['mc_gross'].' - '.SITE_NAME_URL, $message);
    $buyerEmail -> mail();
    $adminEmail = new Email(SITE_EMAIL, 'Product(s) Download Credentials - $'.$ipn_data['mc_gross'].' - '.SITE_NAME_URL, $message);
    $adminEmail -> mail();
}

You can see I'm sending 2 emails ($buyerEmail and $adminEmail) of the same message body to SITE_EMAIL ([email protected]) which is my email and to $ipn_data['payer_email'] which is the PayPal email of the buyer.

My SITE_EMAIL ([email protected]) is an email hosted at Google Apps and it always receives this message. When I click on the message header details it is correctly mailed-by and signed-by my site example.com: http://postimg.org/image/jaow7tpwx/

However, about 30% - 50% of the customers are complaining about not receiving the message after payment and I have to manually forward the same message (that I received) to them. This is frustrating because:

  1. I can't easily debug what's wrong since I can't access their email accounts.
  2. Some customers who were tired of waiting hours for my reply just pulled their money back before I could check my email and manually send the message to them. Economic loss.

I tried to ask them about this. Some said they found the message in the spam folder (I thought correctly mailed-by and signed-by messages never end up there!) and some said they never found it any where, even after days of payment.

Any idea what could be wrong here?

Or is there any better approach than PHP mail()? That would have a much higher delivery rate? Am I better off using a 3rd party service or an SMTP?

What's the best practice here for guaranteeing delivery and not being identified spam?

Upvotes: 1

Views: 122

Answers (1)

Kai
Kai

Reputation: 277

I to had issues when using PHP mail() and some messages not being delivered. I'm guessing that the headers are not perfect when using mail(). The only way I found around the issue was to install PHP Pear Mail library onto the server and using SMTP with PEAR to send the email.

You will want to include other headers not just the below. This is just a simple example of how to send an email with PEAR and via smtp.

require_once "Mail.php";

$from = "Your Name <[email protected]>";
$to = '[email protected]';
$subject = "Some Subject";
$body = "Some Message";

$host = "smtp.yourhost.com";  
$port = "25";

$headers = array ('From' => $from,
   'To' => $to,
   'Subject' => $subject);
$smtp = Mail::factory('smtp',
   array ('host' => $host,
     'port' => $port,
     'auth' => false));

$mail = $smtp->send($to, $headers, $body);

NOTE: You can also do authenticated smtp by defining the username & password and setting auth => true

Upvotes: 1

Related Questions