<?php
$name = $_POST['name'];
$email = $_POST['email'];
$message = $_POST['message'];
$from = 'From: yoursite.com';
$to = 'contact#yoursite.com';
$subject = 'Customer Inquiry';
$body = "From: $name\n E-Mail: $email\n Message:\n $message";
if ($_POST['submit']) {
if (mail ($to, $subject, $body, $from)) {
echo '<p>Your message has been sent!</p>';
} else {
echo '<p>Something went wrong, go back and try again!</p>';
}
}
?>
I've tried creating a simple mail form. The form itself is on my index.html page, but it submits to a separate "thank you for your submission" page, thankyou.php, where the above PHP code is embedded.
The code submits perfectly, but never sends an email. How can I fix this?
Although there are portions of this answer that apply only to the usage of themail() function itself, many of these troubleshooting steps can be applied to any PHP mailing system.
There are a variety of reasons your script appears to not be sending emails. It's difficult to diagnose these things unless there is an obvious syntax error. Without one, you need to run through the checklist below to find any potential pitfalls you may be encountering.
Make sure error reporting is enabled and set to report all errors
Error reporting is essential to rooting out bugs in your code and general errors that PHP encounters. Error reporting needs to be enabled to receive these errors. Placing the following code at the top of your PHP files (or in a master configuration file) will enable error reporting.
error_reporting(-1);
ini_set('display_errors', 'On');
set_error_handler("var_dump");
See How can I get useful error messages in PHP? — this answer for more details on this.
Make sure the mail() function is called
It may seem silly but a common error is to forget to actually place the mail() function in your code. Make sure it is there and not commented out.
Make sure the mail() function is called correctly
bool mail ( string $to, string $subject, string $message [, string $additional_headers [, string $additional_parameters ]] )
The mail function takes three required parameters and optionally a fourth and fifth one. If your call to mail() does not have at least three parameters it will fail.
If your call to mail() does not have the correct parameters in the correct order it will also fail.
Check the server's mail logs
Your web server should be logging all attempts to send emails through it. The location of these logs will vary (you may need to ask your server administrator where they are located) but they can commonly be found in a user's root directory under logs. Inside will be error messages the server reported, if any, related to your attempts to send emails.
Check for Port connection failure
Port block is a very common problem that most developers face while integrating their code to deliver emails using SMTP. And, this can be easily traced at the server maillogs (the location of the server of mail log can vary from server to server, as explained above). In case you are on a shared hosting server, ports 25 and 587 remain blocked by default. This block is been purposely done by your hosting provider. This is true even for some of the dedicated servers. When these ports are blocked, try to connect using port 2525. If you find that the port is also blocked, then the only solution is to contact your hosting provider to unblock these ports.
Most of the hosting providers block these email ports to protect their network from sending any spam emails.
Use ports 25 or 587 for plain/TLS connections and port 465 for SSL connections. For most users, it is suggested to use port 587 to avoid rate limits set by some hosting providers.
Don't use the error suppression operator
When the error suppression operator # is prepended to an expression in PHP, any error messages that might be generated by that expression will be ignored. There are circumstances where using this operator is necessary but sending mail is not one of them.
If your code contains #mail(...) then you may be hiding important error messages that will help you debug this. Remove the # and see if any errors are reported.
It's only advisable when you check with error_get_last() right afterward for concrete failures.
Check the mail() return value
The mail() function:
Returns TRUE if the mail was successfully accepted for delivery, FALSE otherwise. It is important to note that just because the mail was accepted for delivery, it does NOT mean the mail will actually reach the intended destination.
This is important to note because:
If you receive a FALSE return value you know the error lies with your server accepting your mail. This probably isn't a coding issue but a server configuration issue. You need to speak to your system administrator to find out why this is happening.
If you receive a TRUE return value it does not mean your email will definitely be sent. It just means the email was sent to its respective handler on the server successfully by PHP. There are still more points of failure outside of PHP's control that can cause the email to not be sent.
So FALSE will help point you in the right direction whereas TRUE does not necessarily mean your email was sent successfully. This is important to note!
Make sure your hosting provider allows you to send emails and does not limit mail sending
Many shared webhosts, especially free webhosting providers, either do not allow emails to be sent from their servers or limit the amount that can be sent during any given time period. This is due to their efforts to limit spammers from taking advantage of their cheaper services.
If you think your host has emailing limits or blocks the sending of emails, check their FAQs to see if they list any such limitations. Otherwise, you may need to reach out to their support to verify if there are any restrictions in place around the sending of emails.
Check spam folders; prevent emails from being flagged as spam
Oftentimes, for various reasons, emails sent through PHP (and other server-side programming languages) end up in a recipient's spam folder. Always check there before troubleshooting your code.
To avoid mail sent through PHP from being sent to a recipient's spam folder, there are various things you can do, both in your PHP code and otherwise, to minimize the chances your emails are marked as spam. Good tips from Michiel de Mare include:
Use email authentication methods, such as SPF, and DKIM to prove that your emails and your domain name belong together, and to prevent spoofing of your domain name. The SPF website includes a wizard to generate the DNS information for your site.
Check your reverse DNS to make sure the IP address of your mail server points to the domain name that you use for sending mail.
Make sure that the IP-address that you're using is not on a blacklist
Make sure that the reply-to address is a valid, existing address.
Use the full, real name of the addressee in the To field, not just the email-address (e.g. "John Smith" <john#blacksmiths-international.com> ).
Monitor your abuse accounts, such as abuse#yourdomain.example and postmaster#yourdomain.example. That means - make sure that these accounts exist, read what's sent to them, and act on complaints.
Finally, make it really easy to unsubscribe. Otherwise, your users will unsubscribe by pressing the spam button, and that will affect your reputation.
See How do you make sure email you send programmatically is not automatically marked as spam? for more on this topic.
Make sure all mail headers are supplied
Some spam software will reject mail if it is missing common headers such as "From" and "Reply-to":
$headers = array("From: from#example.com",
"Reply-To: replyto#example.com",
"X-Mailer: PHP/" . PHP_VERSION
);
$headers = implode("\r\n", $headers);
mail($to, $subject, $message, $headers);
Make sure mail headers have no syntax errors
Invalid headers are just as bad as having no headers. One incorrect character could be all it takes to derail your email. Double-check to make sure your syntax is correct as PHP will not catch these errors for you.
$headers = array("From from#example.com", // missing colon
"Reply To: replyto#example.com", // missing hyphen
"X-Mailer: "PHP"/" . PHP_VERSION // bad quotes
);
Don't use a faux From: sender
While the mail must have a From: sender, you may not just use any value. In particular user-supplied sender addresses are a surefire way to get mails blocked:
$headers = array("From: $_POST[contactform_sender_email]"); // No!
Reason: your web or sending mail server is not SPF/DKIM-whitelisted to pretend being responsible for #hotmail or #gmail addresses. It may even silently drop mails with From: sender domains it's not configured for.
Make sure the recipient value is correct
Sometimes the problem is as simple as having an incorrect value for the recipient of the email. This can be due to using an incorrect variable.
$to = 'user#example.com';
// other variables ....
mail($recipient, $subject, $message, $headers); // $recipient should be $to
Another way to test this is to hard code the recipient value into the mail() function call:
mail('user#example.com', $subject, $message, $headers);
This can apply to all of the mail() parameters.
Send to multiple accounts
To help rule out email account issues, send your email to multiple email accounts at different email providers. If your emails are not arriving at a user's Gmail account, send the same emails to a Yahoo account, a Hotmail account, and a regular POP3 account (like your ISP-provided email account).
If the emails arrive at all or some of the other email accounts, you know your code is sending emails but it is likely that the email account provider is blocking them for some reason. If the email does not arrive at any email account, the problem is more likely to be related to your code.
Make sure the code matches the form method
If you have set your form method to POST, make sure you are using $_POST to look for your form values. If you have set it to GET or didn't set it at all, make sure you use $_GET to look for your form values.
Make sure your form action value points to the correct location
Make sure your form action attribute contains a value that points to your PHP mailing code.
<form action="send_email.php" method="POST">
Make sure the Web host supports sending email
Some Web hosting providers do not allow or enable the sending of emails through their servers. The reasons for this may vary but if they have disabled the sending of mail you will need to use an alternative method that uses a third party to send those emails for you.
An email to their technical support (after a trip to their online support or FAQ) should clarify if email capabilities are available on your server.
Make sure the localhost mail server is configured
If you are developing on your local workstation using WAMP, MAMP, or XAMPP, an email server is probably not installed on your workstation. Without one, PHP cannot send mail by default.
You can overcome this by installing a basic mail server. For Windows, you can use the free Mercury Mail.
You can also use SMTP to send your emails. See this great answer from Vikas Dwivedi to learn how to do this.
Enable PHP's custom mail.log
In addition to your MTA's and PHP's log file, you can enable logging for the mail() function specifically. It doesn't record the complete SMTP interaction, but at least function call parameters and invocation script.
ini_set("mail.log", "/tmp/mail.log");
ini_set("mail.add_x_header", TRUE);
See http://php.net/manual/en/mail.configuration.php for details. (It's best to enable these options in the php.ini or .user.ini or .htaccess perhaps.)
Check with a mail testing service
There are various delivery and spamminess checking services you can utilize to test your MTA/webserver setup. Typically you send a mail probe To: their address, then get a delivery report and more concrete failures or analyses later:
mail-tester.example (free/simple)
glockapps.com (free/$$$)
senforensics.com (signup/$$$)
mailtrap.io (pro/$$$)
ultratools/…/emailTest (free/MX checks only)
Various: http://www.verticalresponse.com/blog/7-email-testing-delivery-tools/
Use a different mailer
PHP's built-in mail() function is handy and often gets the job done but it has its shortcomings. Fortunately, there are alternatives that offer more power and flexibility including handling a lot of the issues outlined above:
Most popular being: PHPMailer
Likewise featureful: SwiftMailer
Or even the older PEAR::Mail.
All of these can be combined with a professional SMTP server/service provider. (Because typical 08/15 shared webhosting plans are hit or miss when it comes to email setup/configurability.)
Add a mail header in the mail function:
$header = "From: noreply#example.com\r\n";
$header.= "MIME-Version: 1.0\r\n";
$header.= "Content-Type: text/html; charset=ISO-8859-1\r\n";
$header.= "X-Priority: 1\r\n";
$status = mail($to, $subject, $message, $header);
if($status)
{
echo '<p>Your mail has been sent!</p>';
} else {
echo '<p>Something went wrong. Please try again!</p>';
}
Always try sending headers in the mail function.
If you are sending mail through localhost then do the SMTP settings for sending mail.
If you are sending mail through a server then check the email sending feature is enabled on your server.
If you are using an SMTP configuration for sending your email, try using PHPMailer instead. You can download the library from https://github.com/PHPMailer/PHPMailer.
I created my email sending this way:
function send_mail($email, $recipient_name, $message='')
{
require("phpmailer/class.phpmailer.php");
$mail = new PHPMailer();
$mail->CharSet = "utf-8";
$mail->IsSMTP(); // Set mailer to use SMTP
$mail->Host = "mail.example.com"; // Specify main and backup server
$mail->SMTPAuth = true; // Turn on SMTP authentication
$mail->Username = "myusername"; // SMTP username
$mail->Password = "p#ssw0rd"; // SMTP password
$mail->From = "me#walalang.com";
$mail->FromName = "System-Ad";
$mail->AddAddress($email, $recipient_name);
$mail->WordWrap = 50; // Set word wrap to 50 characters
$mail->IsHTML(true); // Set email format to HTML (true) or plain text (false)
$mail->Subject = "This is a Sampleenter code here Email";
$mail->Body = $message;
$mail->AltBody = "This is the body in plain text for non-HTML mail clients";
$mail->AddEmbeddedImage('images/logo.png', 'logo', 'logo.png');
$mail->addAttachment('files/file.xlsx');
if(!$mail->Send())
{
echo "Message could not be sent. <p>";
echo "Mailer Error: " . $mail->ErrorInfo;
exit;
}
echo "Message has been sent";
}
Just add some headers before sending mail:
<?php
$name = $_POST['name'];
$email = $_POST['email'];
$message = $_POST['message'];
$from = 'From: yoursite.com';
$to = 'contact#yoursite.com';
$subject = 'Customer Inquiry';
$body = "From: $name\n E-Mail: $email\n Message:\n $message";
$headers .= "MIME-Version: 1.0\r\n";
$headers .= "Content-type: text/html\r\n";
$headers .= 'From: from#example.com' . "\r\n" .
'Reply-To: reply#example.com' . "\r\n" .
'X-Mailer: PHP/' . phpversion();
mail($to, $subject, $message, $headers);
And one more thing. The mail() function is not working in localhost. Upload your code to a server and try.
It worked for me on 000webhost by doing the following:
$headers = "MIME-Version: 1.0" . "\r\n";
$headers .= "Content-type: text/html; charset=iso-8859-1" . "\r\n";
$headers .= "From: ". $from. "\r\n";
$headers .= "Reply-To: ". $from. "\r\n";
$headers .= "X-Mailer: PHP/" . phpversion();
$headers .= "X-Priority: 1" . "\r\n";
Enter directly the email address when sending the email:
mail('email#gmail.com', $subject, $message, $headers)
Use '' and not "".
This code works, but the email was received with half an hour lag.
Mostly the mail() function is disabled in shared hosting.
A better option is to use SMTP. The best option would be Gmail or SendGrid.
SMTPconfig.php
<?php
$SmtpServer="smtp.*.*";
$SmtpPort="2525"; //default
$SmtpUser="***";
$SmtpPass="***";
?>
SMTPmail.php
<?php
class SMTPClient
{
function SMTPClient ($SmtpServer, $SmtpPort, $SmtpUser, $SmtpPass, $from, $to, $subject, $body)
{
$this->SmtpServer = $SmtpServer;
$this->SmtpUser = base64_encode ($SmtpUser);
$this->SmtpPass = base64_encode ($SmtpPass);
$this->from = $from;
$this->to = $to;
$this->subject = $subject;
$this->body = $body;
if ($SmtpPort == "")
{
$this->PortSMTP = 25;
}
else
{
$this->PortSMTP = $SmtpPort;
}
}
function SendMail ()
{
$newLine = "\r\n";
$headers = "MIME-Version: 1.0" . $newLine;
$headers .= "Content-type: text/html; charset=iso-8859-1" . $newLine;
if ($SMTPIN = fsockopen ($this->SmtpServer, $this->PortSMTP))
{
fputs ($SMTPIN, "EHLO ".$HTTP_HOST."\r\n");
$talk["hello"] = fgets ( $SMTPIN, 1024 );
fputs($SMTPIN, "auth login\r\n");
$talk["res"]=fgets($SMTPIN,1024);
fputs($SMTPIN, $this->SmtpUser."\r\n");
$talk["user"]=fgets($SMTPIN,1024);
fputs($SMTPIN, $this->SmtpPass."\r\n");
$talk["pass"]=fgets($SMTPIN,256);
fputs ($SMTPIN, "MAIL FROM: <".$this->from.">\r\n");
$talk["From"] = fgets ( $SMTPIN, 1024 );
fputs ($SMTPIN, "RCPT TO: <".$this->to.">\r\n");
$talk["To"] = fgets ($SMTPIN, 1024);
fputs($SMTPIN, "DATA\r\n");
$talk["data"]=fgets( $SMTPIN,1024 );
fputs($SMTPIN, "To: <".$this->to.">\r\nFrom: <".$this->from.">\r\n".$headers."\n\nSubject:".$this->subject."\r\n\r\n\r\n".$this->body."\r\n.\r\n");
$talk["send"]=fgets($SMTPIN,256);
//CLOSE CONNECTION AND EXIT ...
fputs ($SMTPIN, "QUIT\r\n");
fclose($SMTPIN);
//
}
return $talk;
}
}
?>
contact_email.php
<?php
include('SMTPconfig.php');
include('SMTPmail.php');
if($_SERVER["REQUEST_METHOD"] == "POST")
{
$to = "";
$from = $_POST['email'];
$subject = "Enquiry";
$body = $_POST['name'].'</br>'.$_POST['companyName'].'</br>'.$_POST['tel'].'</br>'.'<hr />'.$_POST['message'];
$SMTPMail = new SMTPClient ($SmtpServer, $SmtpPort, $SmtpUser, $SmtpPass, $from, $to, $subject, $body);
$SMTPChat = $SMTPMail->SendMail();
}
?>
If you only use the mail()function, you need to complete the configuration file.
You need to open the mail expansion, and set the SMTP smtp_port and so on, and most important, your username and your password. Without that, mail cannot be sent. Also, you can use the PHPMail class to send.
Try these two things separately and together:
remove the if($_POST['submit']){}
remove $from (just my gut)
I think this should do the trick. I just added an if(isset and added concatenation to the variables in the body to separate PHP from HTML.
<?php
$name = $_POST['name'];
$email = $_POST['email'];
$message = $_POST['message'];
$from = 'From: yoursite.com';
$to = 'contact#yoursite.com';
$subject = 'Customer Inquiry';
$body = "From:" .$name."\r\n E-Mail:" .$email."\r\n Message:\r\n" .$message;
if (isset($_POST['submit']))
{
if (mail ($to, $subject, $body, $from))
{
echo '<p>Your message has been sent!</p>';
}
else
{
echo '<p>Something went wrong, go back and try again!</p>';
}
}
?>
For anyone who finds this going forward, I would not recommend using mail. There's some answers that touch on this, but not the why of it.
PHP's mail function is not only opaque, it fully relies on whatever MTA you use (i.e. Sendmail) to do the work. mail will only tell you if the MTA failed to accept it (i.e. Sendmail was down when you tried to send). It cannot tell you if the mail was successful because it's handed it off. As such (as John Conde's answer details), you now get to fiddle with the logs of the MTA and hope that it tells you enough about the failure to fix it. If you're on a shared host or don't have access to the MTA logs, you're out of luck. Sadly, the default for most vanilla installs for Linux handle it this way.
A mail library (PHPMailer, Zend Framework 2+, etc.), does something very different from mail. They open a socket directly to the receiving mail server and then send the SMTP mail commands directly over that socket. In other words, the class acts as its own MTA (note that you can tell the libraries to use mail to ultimately send the mail, but I would strongly recommend you not do that).
This means you can then directly see the responses from the receiving server (in PHPMailer, for instance, you can turn on debugging output). No more guessing if a mail failed to send or why.
If you're using SMTP (i.e. you're calling isSMTP()), you can get a detailed transcript of the SMTP conversation using the SMTPDebug property.
Set this option by including a line like this in your script:
$mail->SMTPDebug = 2;
You also get the benefit of a better interface. With mail you have to set up all your headers, attachments, etc. With a library, you have a dedicated function to do that. It also means the function is doing all the tricky parts (like headers).
$name = $_POST['name'];
$email = $_POST['email'];
$reciver = '/* Reciver Email address */';
if (filter_var($reciver, FILTER_VALIDATE_EMAIL)) {
$subject = $name;
// To send HTML mail, the Content-type header must be set.
$headers = 'MIME-Version: 1.0' . "\r\n";
$headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";
$headers .= 'From:' . $email. "\r\n"; // Sender's Email
//$headers .= 'Cc:' . $email. "\r\n"; // Carbon copy to Sender
$template = '<div style="padding:50px; color:white;">Hello ,<br/>'
. '<br/><br/>'
. 'Name:' .$name.'<br/>'
. 'Email:' .$email.'<br/>'
. '<br/>'
. '</div>';
$sendmessage = "<div style=\"background-color:#7E7E7E; color:white;\">" . $template . "</div>";
// Message lines should not exceed 70 characters (PHP rule), so wrap it.
$sendmessage = wordwrap($sendmessage, 70);
// Send mail by PHP Mail Function.
mail($reciver, $subject, $sendmessage, $headers);
echo "Your Query has been received, We will contact you soon.";
} else {
echo "<span>* invalid email *</span>";
}
You can use config email by CodeIgniter. For example, using SMTP (simple way):
$config = Array(
'protocol' => 'smtp',
'smtp_host' => 'mail.domain.com', // Your SMTP host
'smtp_port' => 26, // Default port for SMTP
'smtp_user' => 'name#domain.com',
'smtp_pass' => 'password',
'mailtype' => 'html',
'charset' => 'iso-8859-1',
'wordwrap' => TRUE
);
$message = 'Your msg';
$this->load->library('email', $config);
$this->email->from('name#domain.com', 'Title');
$this->email->to('emaildestination#domain.com');
$this->email->subject('Header');
$this->email->message($message);
if($this->email->send())
{
// Conditional true
}
It works for me!
Try this
if ($_POST['submit']) {
$success= mail($to, $subject, $body, $from);
if($success)
{
echo '
<p>Your message has been sent!</p>
';
} else {
echo '
<p>Something went wrong, go back and try again!</p>
';
}
}
Maybe the problem is the configuration of the mail server. To avoid this type of problems or you do not have to worry about the mail server problem, I recommend you use PHPMailer.
It is a plugin that has everything necessary to send mail, and the only thing you have to take into account is to have the SMTP port (Port: 25 and 465), enabled.
require_once 'PHPMailer/PHPMailer.php';
require_once '/servicios/PHPMailer/SMTP.php';
require_once '/servicios/PHPMailer/Exception.php';
$mail = new \PHPMailer\PHPMailer\PHPMailer(true);
try {
//Server settings
$mail->SMTPDebug = 0;
$mail->isSMTP();
$mail->Host = 'smtp.gmail.com';
$mail->SMTPAuth = true;
$mail->Username = 'correo#gmail.com';
$mail->Password = 'contrasenia';
$mail->SMTPSecure = 'ssl';
$mail->Port = 465;
// Recipients
$mail->setFrom('correo#gmail.com', 'my name');
$mail->addAddress('destination#correo.com');
// Attachments
$mail->addAttachment('optional file'); // Add files, is optional
// Content
$mail->isHTML(true);// Set email format to HTML
$mail->Subject = utf8_decode("subject");
$mail->Body = utf8_decode("mail content");
$mail->AltBody = '';
$mail->send();
}
catch (Exception $e) {
$error = $mail->ErrorInfo;
}
First of all, you might have too many parameters for the mail() function...
You are able to have of maximum of five, mail(to, subject, message, headers, parameters);
As far as the $from variable goes, that should automatically come from your webhost if your using the Linux cPanel. It automatically comes from your cPanel username and IP address.
$name = $_POST['name'];
$email = $_POST['email'];
$message = $_POST['message'];
$from = 'From: yoursite.com';
$to = 'contact#yoursite.com';
$subject = 'Customer Inquiry';
$body = "From: $name\n E-Mail: $email\n Message:\n $message";
Also make sure you have the correct order of variables in your mail() function.
The mail($to, $subject, $message, etc.) in that order, or else there is a chance of it not working.
This will only affect a small handful of users, but I'd like it documented for that small handful. This member of that small handful spent 6 hours troubleshooting a working PHP mail script because of this issue.
If you're going to a university that runs XAMPP from www.AceITLab.com, you should know what our professor didn't tell us: The AceITLab firewall (not the Windows firewall) blocks MercuryMail in XAMPP. You'll have to use an alternative mail client, pear is working for us. You'll have to send to a Gmail account with low security settings.
Yes, I know, this is totally useless for real world email. However, from what I've seen, academic settings and the real world often have precious little in common.
Make sure you have Sendmail installed in your server.
If you have checked your code and verified that there is nothing wrong there, go to /var/mail and check whether that folder is empty.
If it is empty, you will need to do a:
sudo apt-get install sendmail
if you are on an Ubuntu server.
For those who do not want to use external mailers and want to mail() on a dedicated Linux server.
The way, how PHP mails, is described in php.ini in section [mail function].
Parameter sendmail-path describes how sendmail is called. The default value is sendmail -t -i, so if you get a working sendmail -t -i < message.txt in the Linux console - you will be done. You could also add mail.log to debug and be sure mail() is really called.
Different MTAs can implement sendmail. They just make a symbolic link to their binaries on that name. For example, in Debian the default is Postfix. Configure your MTA to send mail and test it from the console with sendmail -v -t -i < message.txt. File message.txt should contain all headers of a message and a body, destination address for the envelope will be taken from the To: header. Example:
From: myapp#example.com
To: mymail#example.com
Subject: Test mail via sendmail.
Text body.
I prefer to use ssmtp as MTA because it is simple and does not require running a daemon with opened ports. ssmtp fits only for sending mail from localhost. It also can send authenticated email via your account on a public mail service. Install ssmtp and edit configuration file /etc/ssmtp/ssmtp.conf. To be able also to receive local system mail to Unix accounts (alerts to root from cron jobs, for example) configure /etc/ssmtp/revaliases file.
Here is my configuration for my account on Yandex mail:
root=mymail#example.com
mailhub=smtp.yandex.ru:465
FromLineOverride=YES
UseTLS=YES
AuthUser=abcde#yandex.ru
AuthPass=password
If you're having trouble sending mails with PHP, consider an alternative like PHPMailer or SwiftMailer.
I usually use SwiftMailer whenever I need to send mails with PHP.
Basic usage:
require 'mail/swift_required.php';
$message = Swift_Message::newInstance()
// The subject of your email
->setSubject('Jane Doe sends you a message')
// The from address(es)
->setFrom(array('jane.doe#gmail.com' => 'Jane Doe'))
// The to address(es)
->setTo(array('frank.stevens#gmail.com' => 'Frank Stevens'))
// Here, you put the content of your email
->setBody('<h3>New message</h3><p>Here goes the rest of my message</p>', 'text/html');
if (Swift_Mailer::newInstance(Swift_MailTransport::newInstance())->send($message)) {
echo json_encode([
"status" => "OK",
"message" => 'Your message has been sent!'
], JSON_PRETTY_PRINT);
} else {
echo json_encode([
"status" => "error",
"message" => 'Oops! Something went wrong!'
], JSON_PRETTY_PRINT);
}
See the official documentation for more information on how to use SwiftMailer.
Sendmail installation for Debian 10.0.0 ('Buster') was in fact trivial!
php.ini
[mail function]
sendmail_path=/usr/sbin/sendmail -t -i
; (Other directives are mostly windows)
Standard sendmail package install (allowing 'send'):
su - # Install as user 'root'
dpkg --list # Is install necessary?
apt-get install sendmail sendmail-cf m4 # Note multiple package selection
sendmailconfig # Respond all 'Y' for new install
Miscellaneous useful commands:
which sendmail # /usr/sbin/sendmail
which sendmailconfig # /usr/sbin/sendmailconfig
man sendmail # Documentation
systemctl restart sendmail # As and when required
Verification (of ability to send)
echo "Subject: sendmail test" | sendmail -v <yourEmail>#gmail.com
The above took about 5 minutes. Then I wasted 5 hours... Don't forget to check your spam folder!
If you are running this code on a local server (i.e your computer for development purposes) it won't send the email to the recipient. It will create a .txt file in a folder named mailoutput.
In the case if you are using a free hosing service, like 000webhost or hostinger, those service providers disable the mail() function to prevent unintended uses of email spoofing, spamming, etc. I prefer you to contact them to see whether they support this feature.
If you are sure that the service provider supports the mail() function, you can check this PHP manual for further reference,
PHP mail()
To check weather your hosting service support the mail() function, try running this code (remember to change the recipient email address):
<?php
$to = 'nobody#example.com';
$subject = 'the subject';
$message = 'hello';
$headers = 'From: webmaster#example.com' . "\r\n" .
'Reply-To: webmaster#example.com' . "\r\n" .
'X-Mailer: PHP/' . phpversion();
mail($to, $subject, $message, $headers);
?>
You can use the PHPMailer and it works perfectly,here's a code example:
<?php
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
require 'vendor/phpmailer/phpmailer/src/Exception.php';
require 'vendor/phpmailer/phpmailer/src/PHPMailer.php';
require 'vendor/phpmailer/phpmailer/src/SMTP.php';
$editor = $_POST["editor"];
$subject = $_POST["subject"];
$to = $_POST["to"];
try {
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$mail = new PHPMailer();
$mail->IsSMTP();
$mail->Mailer = "smtp";
$mail->SMTPDebug = 1;
$mail->SMTPAuth = TRUE;
$mail->SMTPSecure = "tls";
$mail->Port = 587;
$mail->Host = "smtp.gmail.com";//using smtp server
$mail->Username = "XXXXXXXXXX#gmail.com";//the email which will send the email
$mail->Password = "XXXXXXXXXX";//the password
$mail->IsHTML(true);
$mail->AddAddress($to, "recipient-name");
$mail->SetFrom("XXXXXXXXXX#gmail.com", "from-name");
$mail->AddReplyTo("XXXXXXXXXX#gmail.com", "reply-to-name");
$mail->Subject = $subject;
$mail->MsgHTML($editor);
if (!$mail->Send()) {
echo "Error while sending Email.";
var_dump($mail);
} else {
echo "Email sent successfully";
}
}
} catch (Exception $e) {
echo $e->getMessage();
}
You can see your errors by:
error_reporting(E_ALL);
And my sample code is:
<?php
use PHPMailer\PHPMailer\PHPMailer;
require 'PHPMailer.php';
require 'SMTP.php';
require 'Exception.php';
$name = $_POST['name'];
$mailid = $_POST['mail'];
$mail = new PHPMailer;
$mail->IsSMTP();
$mail->SMTPDebug = 0; // Set mailer to use SMTP
$mail->Host = 'smtp.gmail.com'; // Specify main and backup server
$mail->Port = 587; // Set the SMTP port
$mail->SMTPAuth = true; // Enable SMTP authentication
$mail->Username = 'someone#gmail.com'; // SMTP username
$mail->Password = 'password'; // SMTP password
$mail->SMTPSecure = 'tls'; // Enable encryption, 'ssl' also accepted
$mail->From = 'someone#gmail.com';
$mail->FromName = 'name';
$mail->AddAddress($mailid, $name); // Name is optional
$mail->IsHTML(true); // Set email format to HTML
$mail->Subject = 'Here is the subject';
$mail->Body = 'Here is your message' ;
$mail->AltBody = 'This is the body in plain text for non-HTML mail clients';
if (!$mail->Send()) {
echo 'Message could not be sent.';
echo 'Mailer Error: ' . $mail->ErrorInfo;
exit;
}
echo 'Message has been sent';
?>
If you're stuck with an app hosted on Hostgator, this is what solved my problem. Thanks a lot to the guy who posted the detailed solution. In case the link goes offline one day, there you have the summary:
Look for the sendmail path in your server. A simple way to check it, is to temporarily write the following code in a page which only you will access, to read the generated info: <?php phpinfo(); ?>. Open this page, and look for sendmail path. (Then, don't forget to remove this code!)
Problem and fix: if your sendmail path is saying only -t -i, then edit your server's php.ini and add the following line: sendmail_path = /usr/sbin/sendmail -t -i;
But, after being able to send mail with PHP mail() function, I learned that it sends not authenticated email, what created another issue. The emails were all falling in my Hotmail's junk mail box, and some emails were never delivered, which I guess is related to the fact that they are not authenticated. That's why I decided to switch from mail() to PHPMailer with SMTP, after all.
<?php
$to = 'name#example.com';
$subject = 'Write your email subject here.';
$message = '
<html>
<head>
<title>Title here</title>
</head>
<body>
<p>Message here</p>
</body>
</html>
';
// Carriage return type (RFC).
$eol = "\r\n";
$headers = "Reply-To: Name <name#example.com>".$eol;
$headers .= "Return-Path: Name <name#example.com>".$eol;
$headers .= "From: Name <name#example.com>".$eol;
$headers .= "Organization: Hostinger".$eol;
$headers .= "MIME-Version: 1.0".$eol;
$headers .= "Content-type: text/html; charset=iso-8859-1".$eol;
$headers .= "X-Priority: 3".$eol;
$headers .= "X-Mailer: PHP".phpversion().$eol;
mail($to, $subject, $message, $headers);
Sending HTML email
While sending an email message you can specify a Mime version, content type and character set to send an HTML email.
Example
The above example will send an HTML email message to name#example.com. You can code this program in such a way that it should receive all content from the user and then it should send an email.
What solved this issue for me was that some providers don't allow external recipients when using php mail:
Change the recipient ($recipient) in the code to a local recipient. This means use an email address from the server's domain, for example if your server domain is www.yourdomain.com then the recipient's email should be someone#yourdomain.com.
Upload the modified php file and retry.
If it's still not working: change the sender ($sender) to a local email (use the same email as used for recipient).
Upload the modified php file and retry.
Hope this helps some!
https://www.arclab.com/en/kb/php/how-to-test-and-fix-php-mail-function.html
I had this problem and found that stripping back the headers helped me to get mail out.
So this:
$headers = "MIME-Version: 1.0;\r\n";
$headers .= "Content-type: text/plain; charset=utf-8;\r\n";
$headers .= "To: ".$recipient."\r\n";
$headers .= "From: ".__SITE_TITLE."\r\n";
$headers .= "Reply-To: ".$sender."\r\n";
became this:
$headers = "From: ".__SITE_TITLE."\r\n";
$headers .= "Reply-To: ".$sender."\r\n";
No need for the To: header.
Mail clients are pretty good at sniffing out URLs and rewriting them as a hyperlink. So I didn't bother writing HTML and specifying text/html in the content-type header. I just threw new lines with \r\n in the message body.
I appreciate this isn't the coding purist's approach but it works for what I need it for.
In my case, the email was well sent but to received because the whole message was in one line of over 998 caracters. I needed to make the lines of maximum length 70 with the following line: wordwrap($email_message, 70, "\r\n");.
https://www.rfc-editor.org/rfc/rfc5322#section-2.1.1
There are two limits that this specification places on the number of characters in a line. Each line of characters MUST be no more than 998 characters, and SHOULD be no more than 78 characters, excluding the CRLF.
There are several possibilities:
You're facing a server problem. The server does not have any mail server. So your mail is not working, because your code is fine and mail is working with type.
You are not getting the posted value. Try your code with a static value.
Use SMTP mails to send mail...
Related
A non-stop wave of distributed smtp auth attacks on my server prompted me to ban non specified IPs from connecting to smtp on my server and sending mail though it. Very effective. (instructions: http://sysadmintips.in/advanced/csf/exim)
However I now cannot use Google Mail (Gmail) to 'Send Mail As' for new accounts without either enabling two-factor authentication (which is a pain as I'm setting this up remotely for my clients) or switching smtp auth back on on my server.
My other option would be to white-list Google Mail's IP addresses.
Google searching discovered this way to retrieve the current Google IP ranges using something along these lines (which I've copied from this page: https://support.google.com/a/answer/60764?hl=en):
nslookup -q=TXT _spf.google.com 8.8.8.8
This returns a list of the domains included in Google's SPF record, such as:
_netblocks.google.com, _netblocks2.google.com, _netblocks3.google.com
Now look up the DNS records associated with those domains, one at a time, like so:
nslookup -q=TXT _netblocks.google.com 8.8.8.8
nslookup -q=TXT _netblocks2.google.com 8.8.8.8
nslookup -q=TXT _netblocks3.google.com 8.8.8.8
The results of these commands contain the current range of addresses.
Can I use the output of these to generate useful content for /etc/csf/csf.smtpauth ?
I can code something to do this in PHP and run it as a cron task as root, but what format is acceptable? Does csf.smtpauth accept IP range declarations? Does it cope OK with IPV6 IPs?
After any change I'll also need to force a restart of csf and lfd automatically so the new IPs are in use. Is that possible from PHP running as root?
Thanks!
Solved.
I've coded up the following PHP which queries Google's SPF records and then, only if required, will replace the existing SMTP Auth block with a new one. It then creates a file which is used as a flag for a bash script to re-start the firewall.
Note that /etc/csf/csf.smtpauth accepts IPV4 and IPV6 addresses and CIDR address ranges.
// Grab current Google SPF IPs...
$dns = dns_get_record('_spf.google.com', DNS_TXT);
if (!$dns)
{
echo "FAILED TO RETRIEVE DNS RECORD<br />\n";
exit;
}
// The variable in which to store the results
$ranges = array();
// Of interest in particular to us is...
$val = $dns[0]['txt'];
preg_match_all("/include:[^\s]+\s/", $val, $matches);
if (sizeof($matches[0]) <= 0)
{
echo "BAD DATA RECEIVED OR FAILED TO DECODE DATA<br />\n";
exit;
}
foreach ($matches[0] as $match)
{
$match = trim($match);
$domain = trim(preg_replace("/include\:/", "", $match));
// Now do it all again for this domain to get the IP range
$dns = dns_get_record($domain, DNS_TXT);
if (!$dns)
{
echo "DNS LOOKUP FAILURE AT PASS 2<br />\n";
exit;
}
$val = $dns[0]['txt'];
preg_match_all("/ip\d:[^\s]+\s/", $val, $ips);
if (sizeof($ips[0])<=0)
{
// At time of writing this is entirely possible as _netblocks3.google.com
// currently holds NO IP ranges
}
else
{
foreach ($ips[0] as $ip)
{
$ip = trim($ip);
if ($ip <> '')
{
$ip = preg_replace("/ip\d\:/", "", $ip);
$ranges[] = $ip;
}
}
}
}
// To be here means we made it without a major problem. Form the new IP range for
// the smtp auth file (/etc/csf/csf.smtpauth) and compare with the existing. Update only if there has
// been a change. Also update only if there are at least N ranges found.
// When I wrote this there were 11 IPV4 ranges and 6 IPV6 ranges so setting
// low limit to 10
$limit = 10;
$filename = '/etc/csf/csf.smtpauth';
if (sizeof($ranges) < $limit)
{
echo "NOT UPDATING RANGES, TOO FEW DISCOVERED, PROBLEM?";
exit;
}
$filerange = "# GOOGLE SPF RESULTS START\n";
$filerange .= join("\n", $ranges);
$filerange .= "\n# GOOGLE SPF RESULTS END";
// Read in existing conf file
$econf = file_get_contents($filename);
if (sizeof($econf)<=0)
{
echo "FAILED TO READ $filename<br />\n";
exit;
}
// Extract the block
if (!preg_match("/\# GOOGLE SPF RESULTS START.+\# GOOGLE SPF RESULTS END/s", $econf, $matches))
{
echo "FAILED TO FIND EXISTING BLOCK. CORRUPT AUTH FILE?<br />\n";
exit;
}
if ($filerange == $matches[0])
{
// IT'S THE SAME DO NOT UPDATE IT!;
exit;
}
// Replace the block entirely
$econf = preg_replace("/\# GOOGLE SPF RESULTS START.+\# GOOGLE SPF RESULTS END/s", $filerange, $econf);
// Write out the new file contents
file_put_contents($filename, $econf);
// Trigger a CSF/LFD restart by creating trigger file.
touch("restartcsflfd");
Then create a CRON task to run this shell script shortly after and each time the above is run:
#!/bin/bash
if [ -f /path-to-file/restartcsflfd ];
then
csf -r
/etc/init.d/lfd restart
rm -f restartcsflfd
echo "RE-STARTED CSF and LFD"
fi
Is there a way to password protect a page with an array of passwords (which in this case is email addresses), and then once someone successfully logs in a notification is sent to a specified email address letting us know that someone has logged in with the given password (email address).
Thanks.
You have to do this with a server-side language like PHP. You can't do this with pure HTML and Javascript, unless you plan to store the usernames and passwords in a plaintext array in your Javascript (Don't do this, it is madness!).
If you use PHP, you can send the username and password data via POST, and have the user accounts stored in a MySQL Database. You can then lookup the username and password and see if they match, and if they do, then you could use something like PHP's mail() function to email the user.
As already mentioned, you'll need to use PHP, and your question unfortunately isn't something that can be answered in a couple of lines.
Below won't fully give you your answers, but it may lead you in the right direction to achieving them:
For a tutorial on user login using PHP $_POST , you could try here. Instead of reading the username and passwords from a mysql database, it would be simple enough to read in from an array defined in your PHP file.
For mail, below is a php function to email users their password once it's been reset. You should be able to get the idea of how the mail() function works from it and what variables to populate so you can change it for your own needs. You would call the email function once you've determined that a user has logged in succesfully.
public static function EmailPassword($user_email, $user, $password)
{
$mailfrom = "user#website.com.au";
$eol = "\n";
$content = $eol;
$content .= "Password for " . $user . " is " . $password . $eol;
$subject = "Pasword reset for " . $user . " at website.com.au";
$boundary = md5(uniqid(time()));
$header = 'From: '.$mailfrom.$eol;
$header .= 'Reply-To: '.$mailfrom.$eol;
$header .= 'MIME-Version: 1.0'.$eol;
$header .= 'Content-Type: multipart/mixed; boundary="'.$boundary.'"'.$eol;
$header .= 'X-Mailer: PHP v'.phpversion().$eol;
$body = 'This is a multi-part message in MIME format.'.$eol.$eol;
$body .= '--'.$boundary.$eol;
$body .= 'Content-Type: text/plain; charset=ISO-8859-1'.$eol;
$body .= 'Content-Transfer-Encoding: 8bit'.$eol;
$body .= $eol.stripslashes($content).$eol;
//send the email
mail($user_email, $subject, $body, $header);
}
Hello guys I am working on webapplication for sending multimedia messages upon user input of their phone numbers. I am successfully able to send emails with images in HTML form. Now, I am trying to send my customers MMS via PHP mail function, but the only thing they receive is the link that I send them with the message.
Here is what I have come up with so far.
<?php
$email = '1234567890#somenetwork.domain';
$link = $_COOKIE["coupon"];
$to = $email;
$subject = 'Some Subject';
$message = " Hello, This is Testing Text 8.0
<a href=\"https://encrypted-tbn0.gstatic.com/images? \
q=tbn:ANd9GcS0dA2aipmy9hwAitgD8U5n8l_afNBvxYc3gnOFi7hOGoGAGIHssw\">Your Link</a> ";
$message->addAttachment("https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS0dA2aipmy9hwAitgD8U5n8l_afNBvxYc3gnOFi7hOGoGAGIHssw", "image/gif");
$headers = 'MIME-Version: 1.0' . "\r\n";
$headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";
$headers .= 'From: someone <support#someone.com>' . "\r\n";
mail($email, $subject, $message, $headers);
?>
When sending to a phone as MMS, you have to send the image as an attachment.
I found the following answer to be very helpful for easily sending attachments, even though it references "mail", not MMS:
Send attachments with PHP Mail()?
One of the issues is that you can't fetch that image in that fashion.
I.e. https://encrypted-tbn0.gstatic.com/images?\
q=tbn:ANd9GcS0dA2aipmy9hwAitgD8U5n8l_afNBvxYc3gnOFi7hOGoGAGIHssw
returns an empty file.
Also, since when can you send MMS via PHP's mail() function?
The most reliable way in my experience to send images via SMS/MMS is to send a WAP push msg.
First of all, I'm new here and PHP :).
My question is about Smtp support. My code is doing send recover password. But my hosting need smtp support. I didn't add it. I read a lot post but my knowledge basic.
How can I add smtp support?
function sendRecover($to, $title, $url, $from, $username, $salt) {
$headers = 'MIME-Version: 1.0' . "\r\n";
$headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";
$headers .= 'From: '.$title.' <'.$from.'>' . "\r\n";
$subject = 'Password Recovery - '.$title;
$message = 'A password recover was requested, if you didn\'t make this action please ignore this email. <br /><br />Your Username: <strong>'.$username.'</strong><br />Your Reset Key: <strong>'.$salt.'</strong><br /><br />You can reset your password by accessing the following link: '.$url.'/index.php?a=recover&r=1';
return #mail($to, $subject, $message, $headers);
}
Use PHPMailer
The current "official" version of PHPMailer is available through Github:
https://github.com/Synchro/PHPMailer
For implementation you can refer the links below :
http://www.htmlgoodies.com/beyond/php/article.php/3855686/PHP-Mailer-Script-Step-by-Step.htm
or
http://phpmailer.worxware.com/index.php?pg=examplebsmtp
If you have access to edit the php.ini then you can do something like this:
[mail function]
SMTP = ssl://smtp.gmail.com
smtp_port = 465
username = info#Mmydomainname.com
password = myemailpassword
sendmail_from = info#mydomainname.com
I have the following script to update one of my FTP passwords every 15 days through a cronjob and e-mail the appropriate people after the attempt has been made. It randomly will fail and so I will run it again manually and it will work. I can't seem to find where it's going wrong.
The script is connecting to a local mysql database grabbing the login and password for an account and then changing that password on FTP. Everything is successful up until the changing the password part. Again it's random, sometimes it works, sometime it doesn't.
Thanks!
#!/usr/bin/perl -w
#
use DBI;
use Net::FTP;
our $dbh = DBI->connect('DBI:mysql:database:127.0.0.1','user','password') or die "Aargh $!\n";
$transquery=q{SELECT dest_login,dest_password FROM list where id=123};
$sth=$dbh->prepare($transquery);
$sth->execute();
while($co=$sth->fetchrow_hashref){
$login=$co->{'dest_login'};
$pass=$co->{'dest_password'};
}
$changeresult='FAIL';
$actionlog='';
$newstring='';
$upperchars='ABCDEFGHIJKLMNOPQRSTUVWXYZ';
$lowerchars='abcdefghijklmnopqrstuvwxyz';
$allowedchars='ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789##$';
$l=length($upperchars);
$newstring.=substr($upperchars,int(rand($l)),1);
$newstring.=substr($lowerchars,int(rand($l)),1);
$l=length($allowedchars);
for ($i=0;$i<6;$i++){
$newstring.=substr($allowedchars,int(rand($l)),1);
}
print "$newstring\n";
$actionlog .= "Setting Password for $login from $pass to $newstring\n";
$username=
eval{
$ftp=Net::FTP->new('x.x.x.x',Timeout=>480,Debug=>1) or die "Error connecting FTP $!\n";
$changepassword="$pass/$newstring/$newstring";
$ftp->login($login,$changepassword) or die "Error changing password $!\n";
#If we are here, time to update the password
$changeresult='SUCCESS';
$actionlog .= "Password successfully updated\n";
$transquery=q{UPDATE list set dest_password=(?) where id=123};
$sth=$dbh->prepare($transquery);
$sth->execute($newstring);
};
if ($#) {
$actionlog = $actionlog . "$#\n";
};
if($actionlog ne ""){
#print $actionlog;
#my $send_to = "To: someone\#example.com\n";
my $send_to = "To: databaseusers\#example.com\n";
my $sendmail = "/usr/sbin/sendmail -t";
open(SENDMAIL, "|$sendmail") or die "Cannot open $sendmail: $!";
print SENDMAIL "Reply-to: databasepassword\#example.com\n";
print SENDMAIL "Subject: Password Change Information [$changeresult]\n";
print SENDMAIL $send_to;
print SENDMAIL "Content-type: text/plain\n\n";
print SENDMAIL $send_to;
print SENDMAIL "Content-type: text/plain\n\n";
print SENDMAIL $actionlog;
close(SENDMAIL);
$actionlog='';
}
else{
#print "Nothing done this session\n";
USUW might tell you something. ( use strict; use warnings; )
Does anything print?
You don't do much error checking in the DBI part at the beginning, perhaps you're getting a connect error. AIX boxes used to have this problem of getting a client port that the system was unsure about whether or not it was in use. When that happened, it would just fail to connect to the database.
I finally fixed that problem for our scripts by examining the $OS_ERROR ( aka $! ) for that particular code ( Errno::EADDRINUSE ) and then waiting and retrying, with an exponential falloff ( wait 2 seconds, then 4, then 8 ... ).
If your script "dies for some reason" then it's important the script can tell you that reason. I would investigate the topic of error reporting in the various modules you are using.
For example Net::FTP allows you to pass a Debug => 1 switch, and then you'll see the whole conversation.
And I know that there is a whole lot more with DBI where you can get error reporting.