Category Archives: email

Troubleshoot Email Issues

I generally dread working with email no matter what system it is on! Here I am going to discuss some useful tips for debugging an email system on a Linux server. I am using an Amazon Linux AMI with Centos, but the process is similar for any Linux server you might have. Below I will discuss how to check error files and how to avoid sending email to spam or junk folders.

Having Trouble Sending Email?

If you're emails are not getting through and you don't know why, check your server's log files. Below I'll show you how to find mist email related error logs. They can normally be found in /var/spool/mail/username which on an Amazon Linux distro would be either:

/var/spool/mail/root

or:

/var/spool/mail/ec2-user

It is important to know that in the above context, username, root and ec2-user are files, NOT directories. To open one of those files, navigate to /var/spool/mail like:

cd /var/spool/mail

To open root file with your Linux command line text editor, type:

sudo vi root

...and check the last errors to see the most recent.

TIP: use [shift]+g to skip to the last line of the file using VI editor.

How to Avoid Sending eMail to Spam or Junk Mail folders

I ran several tests to find the best way to send emails from the command line without ending up in the recipient's spam or junk mail folder. Since I was using an Amazon EC2 instance with SES, I will explain the server setup used and then show the results of the tests. Some went to spam immediately and others went straight to the recipient's In Box as it should.

Amazon EC2, SES and sendmail environment

Here are the circumstances that my test cases were executed under:

The following command line commands sent emails to my In Box:

  • /usr/sbin/sendmail linian11@yahoo.com
  • sudo mail linian11@yahoo.com
  • mail linian11@yahoo.com

The following command line commands sent emails to my Spam:

  • /usr/sbin/sendmail -f SESverified@email.com linian11@yahoo.com
  • sudo /usr/sbin/sendmail -f SESverified@email.com linisn11@yahoo.com
  • sudo /usr/sbin/sendmail linian11@yahoo.com

In the above examples, I didn't use parameters for subject, CC or BCC because they don't seem to make any difference. Only  using sendmail, sudo and the -f parameter made a difference to determine if the emails were delivered to my in box or spam folder.

As you can see from the above spam tests, the best way to avoid spam is to:

  • Avoid using the -f parameter even with an SES verified email address.
  • While /usr/sbin/sendmail method did work when avoiding both the -f param and the sudo command, the mail method worked with or without sudo.
  • Either use /usr/sbin/sendmail without -f parameter and without using sudo, or use mail for the best chances of your email getting through to your recipients in boxes.

 

Open .txt File Peel Off One Line and Save File with PHP

This code snippet will demonstrate how to use PHP to open a .txt file or any other plain text  file such as .php, .html, .xml etc., retrieve the text in the first line of the file, delete that line and save the file. We are effectively peeling off one line from the file and saving it using pure PHP. Here is how:

<?php
//included in index-cron.php to peel off one keyword from keywords.txt file and use it saving rest back to file.
//turn debugging on/off:
$debug = true;
//read in keyword phrases from keywords.txt file:
$lines = "";
$file = fopen("keywords.txt", "r") or exit("Unable to open keywords.txt file!");
//Output a line of the file until the end is reached:
$line_no=0;
    while(!feof($file)) {
    $line_no++;
    $line = fgets($file);
    $alllines .= $line."<br>";
    //code to later delete first line from keywords.txt file:
        if($line_no > 1){//if over line 1, store in writelines var to write back to file later.
        $writelines .= $line;
        }else{//else line no. is NOT over 1, so store line in cur_keywrd var:
        $curkey = trim($line);
        $cur_keywrd = $curkey;
        }//end else line is under 1 so put in cur_keywrd var.
    }//end while reading in lines from keywords.txt file
fclose($file);
if($debug) echo "<h2>Keyword taken from keywords.txt file: $cur_keywrd</h2><hr>";

//now rewrite keywords.txt file with all but first 1 lines:
$kfile = 'keywords.txt';
$fh = fopen($kfile, 'w') or die("ERROR! Cannot open $kfile file for saving Keywords back to it!");
fwrite($fh, $writelines);
fclose($fh);
if($debug) echo "keyword $cur_keywrd Deleted from keywords.txt file!<hr>";
?>

There you have it! Copy and paste the above code into a .php file named fetch_keywords.php. Now let's test it...

Make a file named keywords.txt and add the following test content to it:

test keyword 1
test keyword 2
test keyword 3
test keyword 4
test keyword 5
test keyword 6
test keyword 7
test keyword 8
test keyword 9
test keyword 10
test keyword 11
test keyword 12

Save keywords.txt and upload it to the same directory as fetch_keywords.php then open fetch_keywords.php in a browser and you will see this:

kwrfds

If your screen looks like the above shot, then you're doing great! If not, debugging time, but it should work. See where it says "test keyword 1"? That's the keyword it peeled from the keywords.txt file. Now try refreshing the page and it will increment to "test keyword 2". Refresh one more time just for fun and see "test keyword 3" appear. Now download keywords.txt and open it and you'll be able to verify that it did indeed remove the first few lines from the file. This is very usefull if you need to use PHP to read in keywords from a file or domains, phone numbers, names, etc from a file to use the data in your script. Have fun with this and if you need to read multiple lines, the first 100 lines in from a file and save it after deleting those 100 lines, read on, I'll show you how to do that too!

How to read the first 100 lines from a file, delete them and save the file

The next PHP snippet I"ll show you was used to read from a huge list of domain names, take the first 100 domains, use them in my script and save the unused domains back to the .txt file.

The code is similar to the above code with some important changes as you can see below:

<?php
//script to peel of first 100 domains from doms.txt file and save it
//turn debugging on/off:
$debug = true;
//read in domain names from doms.txt file:
$lines = "";
$file = fopen("doms.txt", "r") or exit("Unable to open doms.txt file!");
//Output a line of the file until the end is reached:
$line_no=0;
    while(!feof($file)) {
    $line_no++;
    $line = fgets($file);
    $alllines .= $line."<br>";
    //code to later delete first 100 lines from doms.txt file:
        if($line_no > 100){//if over line 100, store in writelines var to write back to file later.
        $writelines .= $line;
        }else{//else line no is NOT over 100, so store line in dom array:
        $uselines .= $line."<br>";
        $curURL = trim($line);
        //if cur URL doesn't conain a TLD, add .com
            if(strpos($curURL,".")===false){
            $curURL = $curURL.".com";
            }//end if curURL doesn't have a dot
        $dom_array[] = $curURL;
        }//end else line is under 100 so put in dom array.
    }//end while reading in lines from doms.txt file
fclose($file);
if($debug) echo"<h2>Domains taken from dom.txt file:</h2>$uselines<hr>";

//now rewrite doms.txt file with all but first 100 lines:
$domFile = 'doms.txt';
$fh = fopen($domFile, 'w') or die("ERROR! Cannot open $domFile file for saving domains back to it!");
fwrite($fh, $writelines);
fclose($fh);
if($debug) echo"Above Domains Deleted from doms.txt file!<hr>";
?>

PHP Mail Function Not Sending

Okay, today, I have a treat for you. If you are having issues with PHP mail, I probably have a solution for you somewhere in my head, so I am going to attempt to put it down here in my blog so it is documented. I work on a lot of different client's websites and most of them have unique servers. It would be nice and easy if everyone used the same server, but that is never the case. There are different things you have to do to get a broken PHP mail function working for different servers, so a good test suite for email is what you need. That is what I'll attempt to provide here. I hope it helps.

Dynamic PHP eMail Testing Tool

screenshot

If you are interested in the professional version of this PHP mail testing tool seen in the above screenshot, contact me, Ian L., by email at linian11@yahoo.com and I'll give you my professional download version for only $20. Otherwise read on to build your own free version. - Ian L

When I discovered that it was a reoccurring issue to fix peoples email sending ability from various servers, I decided it is time to build a dynamic email tester in PHP. So open up your favorite notepad or editing tool and copy and paste the following code. This is my custom PHP email testing tool I made to test various attributes of the PHP mail function for use with different web servers The tool consists of two very basic PHP files. I'll call them email_form.php and email_sender.php. Put both files in the directory you want to test and start your trial and error testing until you get an email to go through to the recipient that wasn't receiving your messages before.

email-form.php

<html>
<head>
<title>Jafty eMail Tester</title>
</head>
<body>
<h1>Jafty eMail Tester</h1>
<p>A simple dynamic testing tool for the PHP mail function. Allows web developers to test sending emails from any server using the PHP mail function with different settings and parameters until they get it working. To start, simply edit the values in the form below and submit to send a test email to the "Send To" address. Good luck!</p>
<?php
//Set timezone:
date_default_timezone_set('America/New_York');

//format date:
$start = getdate();
$smon = $start['mon'];
$sday = $start['mday'];
$syear = $start['year'];
$shr = $start['hours'];
$smin = $start['minutes'];
$ssec = $start['seconds'];
$formatted_date =  "$smon/$sday/$syear"." "."$shr:$smin:$ssec";
echo "Current Date/Time: ".$formatted_date."<br /><span style='font-size:10px;color:#343434'>(If above time is not correct, change the setting for date_default_timezone_set in email_form.php)</span><br />";

//Set default form field values:
$message = "Test eMail from Jafty PHP mail Tester sent at $formatted_date";
$to = "linian11@yahoo.com";
$subject = "PHP Mail Test";
$headers = "From: peter@petermichaelsonjewellery.com.au\r\n";
$param = "-fpeter@petermichaelsonjewellery.com.au";
?>

<form id="emlform" method="post" action="email_sender.php">
<table><tr><td>
Email Header:
</td><td>
<input type="text" name="h" style="width:450px;" value="<?php echo $headers; ?>" />
</td></tr><tr><td>
Sent To:
</td><td>
<input type="text" name="e" style="width:450px;" value="<?php echo $to; ?>" /></td></tr><tr><td>
Subject:
</td><td>
<input type="text" name="s" style="width:450px;" value="<?php echo $subject; ?>" /></td></tr><tr><td>
Message:
</td><td>
<input type="text" name="m" style="width:450px;" value="<?php echo $message; ?>" /></td></tr><tr><td colspan="2">
<input style="float:right" type="submit" />
</td></tr></table>
<hr><h3>
Here are email accounts for testing with:</h3>
<table><tr><th>
Email
</th><th>
Password
</th></tr><tr><td>
example@hotmail.com
</td><td>
yourpass
</td></tr><tr><td>
example@gmail.com
</td><td>
yourpassword
</td></tr><tr><td>
some-email@example.com
</td><td>
add pass here
</td></tr><tr><td>
test@gmail.com
</td><td>
passhere
</td></tr></table>

<hr /><p>&copy; Copyright 2014-2024 Jafty Interactive Web Development & <a href="http://jafty.com">Jafty.com</a></p>
</body>
</html>

Once you copy and paste the contents of email-form.php, then do the same in a new file for email-sender.php below.

email-sender.php

<?php
$h = $_POST['h'];
$e = $_POST['e'];
$s = $_POST['s'];
$m = $_POST['m'];
$f = "-fpeter@petermichaelsonjewellery.com.au";
//print form values for debugging:
echo "email: $e<br>";
echo "subj: $s<br>";
echo "msg: $m<br>";
echo "header: $h<br>";
echo "optional: $f<hr>";
//send mail:
if(mail($e, $s, $m, $h,$f)){//if mail sent according to mail function:
echo "mail sent!<br>";
}else{//else email failed
echo "ERROR sending email. Details follow if available:<br />";
print_r(error_get_last());
}//end else email failed.
?>

Summary

That is all there is to the tool, but there are other things to learn about php mail, so check the trusty php.net page for php mail at: http://php.net/manual/en/function.mail.php

How to replace wp_mail Function with PHP mail function in WordPress

Be aware that this modification should probably only be used in extreme cases where you can not get WordPress to send emails any other way because this method requires changes to the WordPress core. Making changes to the core files means that you could loose those changes if you update to a different version of WordPress in the future. If you update, you will have to make the changes again. Luckily it is one simple change to one file, so it's not really that bad. I often prefer to use such a hack instead of adding another plugin to my WordPress blog.

To replace the default wp_mail function with one that users PHP mail, find the pluggable.php file located in wp-includes  and replace that wp_mail function with this one:

<?php
function wp_mail( $to, $subject, $message, $headers = '', $attachments = array() ) {
//WP mail function code replaced by Ian L of jafty.com:
// Use wordwrap() if lines are longer than 70 characters
$txt = wordwrap($message,70);
//Always set content-type in headers when sending HTML email:
$headersnew = "MIME-Version: 1.0" . "\r\n";
$headersnew .= "Content-type:text/html;charset=UTF-8" . "\r\n";
//Use headers to set from address:
$headersnew .= "From: peter@michaelson.com.au\r\n";
// Send email:
    if(mail($to,$subject,$txt,$headersnew)) {
    //if mail sent to user send notice to admin:
    $adminsubject = "Admin Notification from WP";
    mail('admin@example.com',$adminsubject,$txt,$headersnew);
    } else {
    //if mail didn't go through, send notice to admin:
    $txterr = "<h2>ERROR!</h2> email to user did not go through!";
    mail('admin@example.com',$subject,$txterr,$headersnew);
    }
}//end php mail function for wp-mail
?>