Функція пошти PHP не завершує надсилання електронної пошти


477
<?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>';
        }
    }
?>

Я спробував створити просту форму пошти. Сама форма знаходиться на моїй index.htmlсторінці, але вона подає окрему сторінку "дякую за подання" thankyou.php, де вбудований вище код PHP. Код подається ідеально, але ніколи не надсилає електронний лист. Як я можу це виправити?


2
це ваша програма на локальному комп’ютері або в прямому ефірі
Tamil Selvan C

6
1. Ви впевнені, що це не входить у вашу спам? 2. Чи налаштовано sendmail на коробці?
Стівен Мозелі

це на живому хості, він не впадає в мій спам.
користувач3818620

спробуйте відправити без$from
Артем Ільченко

Відповіді:


512

Хоча є частини цього відповіді, які стосуються лише використанняmail() функції, багато з цих етапів усунення несправностей можуть бути застосовані до будь-якої системи розсилки PHP.

Існує безліч причин, за якими ваш сценарій не надсилає електронні листи. Діагностувати ці речі важко, якщо немає явної синтаксичної помилки. Без жодного вам потрібно пройти через контрольний список нижче, щоб знайти потенційні підводні камені, з якими ви можете зіткнутися.

Переконайтеся, що увімкнено повідомлення про помилки та встановлено, щоб повідомляти про всі помилки

Повідомлення про помилки має важливе значення для усунення помилок у вашому коді та загальних помилок, з якими стикається PHP. Щоб отримувати ці помилки, потрібно увімкнути повідомлення про помилки. Якщо розмістити наступний код у верхній частині файлів PHP (або в головному файлі конфігурації), ви зможете повідомити про помилки.

error_reporting(-1);
ini_set('display_errors', 'On');
set_error_handler("var_dump");

Див. Як я можу отримати корисні повідомлення про помилки в PHP? - ця відповідь для більш детальної інформації про це.

Переконайтеся, що mail() функція викликана

Це може здатися дурним, але поширена помилка - забути насправді розмістити своє місце mail() функцію у своєму коді. Переконайтесь, що він там є, а не коментується.

Переконайтесь, що mail()функція викликана правильно

bool mail (рядок $ to, string $ subject, string $ message [, рядок $ Additional_headers [, рядок $ Additional_parameters]])

Функція пошти приймає три необхідні параметри та необов'язково четвертий та п'ятий. Якщо ваш дзвінок наmail() не має принаймні трьох параметрів, він вийде з ладу.

Якщо ваш дзвінок на mail() не має правильних параметрів у правильному порядку, він також не вдасться.

Перевірте журнали пошти сервера

Ваш веб-сервер повинен реєструвати всі спроби надсилання електронної пошти через нього. Розташування цих журналів буде відрізнятися (можливо, вам доведеться запитати адміністратора сервера, де вони знаходяться), але їх зазвичай можна знайти в кореневій директорії користувача під logs. Всередині будуть повідомлення про помилки, про які повідомляється сервер, якщо такі є, пов’язані з вашими спробами надсилання електронних листів.

Перевірте наявність порту підключення

Блок порту є дуже поширеною проблемою, з якою стикається більшість розробників, інтегруючи свій код для доставки електронних листів за допомогою SMTP. І це легко простежується в поштових журналах сервера (місце розташування сервера журналу пошти може відрізнятися від сервера до сервера, як пояснено вище). Якщо ви перебуваєте на спільному сервері хостингу, порти 25 і 587 залишаються заблокованими за замовчуванням. Цей блок спеціально зробив ваш хостинг-провайдер. Це справедливо навіть для деяких виділених серверів. Коли ці порти заблоковані, спробуйте підключитися за допомогою порту 2525. Якщо ви виявите, що порт також заблокований, єдине рішення - зв’язатися зі своїм постачальником хостингу, щоб розблокувати ці порти.

Більшість хостинг-провайдерів блокують ці порти електронної пошти, щоб захистити їх мережу від надсилання будь-яких спам-листів.

Використовуйте порти 25 або 587 для звичайних / TLS-з'єднань і порт 465 для з'єднань SSL. Для більшості користувачів рекомендується використовувати порт 587, щоб уникнути обмежень тарифів, встановлених деякими хостинг-провайдерами.

Не використовуйте оператора придушення помилок

Коли оператор придушення помилок @ створює претензію на вираз у PHP, будь-які повідомлення про помилки, які можуть бути згенеровані цим виразом, ігноруються. Є обставини, коли використання цього оператора є необхідним, але відправлення пошти не є однією з них.

Якщо ваш код містить, @mail(...)то ви можете приховувати важливі повідомлення про помилки, які допоможуть вам налагодити це. Вийміть @і перевірте, чи повідомляються про якісь помилки.

Це доцільно лише тоді, коли ви відразу ж перевірите наявністьerror_get_last() конкретних відмов.

Перевірте mail() значення повернення

mail()функція:

Повертається, TRUEякщо повідомлення було успішно прийнято для доставки, в FALSEіншому випадку. Важливо зауважити, що лише тому, що пошта була прийнята для доставки, це НЕ означає, що пошта дійсно досягне призначеного пункту призначення.

Це важливо зазначити, оскільки:

  • Якщо ви отримуєте FALSEповернене значення, ви знаєте, що помилка полягає в тому, що ваш сервер приймає вашу пошту. Це, ймовірно, не проблема кодування, а проблема конфігурації сервера. Вам потрібно поговорити з вашим системним адміністратором, щоб з’ясувати, чому це відбувається.
  • Якщо ви отримаєте TRUEповернене значення, це не означає, що ваш електронний лист обов’язково буде надісланий. Це просто означає, що повідомлення електронною поштою було надіслано PHP відповідному обробнику на сервері. Ще є точки відмови поза контролем PHP, які можуть призвести до не надсилання електронної пошти.

Таким чином, FALSEви допоможете направити вас у правильному напрямку, тоді як TRUEце не обов'язково означає, що ваш електронний лист був відправлений успішно. Це важливо відзначити!

Переконайтеся, що ваш постачальник послуг хостингу дозволяє вам надсилати електронні листи та не обмежує надсилання пошти

Багато спільних веб-хостингів, особливо безкоштовні провайдери хостингу, або не дозволяють надсилати електронні листи зі своїх серверів, або обмежують кількість, яку можна надіслати протягом будь-якого певного періоду часу. Це пов’язано з їхніми зусиллями щодо обмеження спамерів від використання їх дешевших послуг.

Якщо ви вважаєте, що у вашого хоста є обмеження в електронній пошті або заблоковано надсилання електронних листів, перегляньте їхні поширені запитання, щоб побачити, чи є в них такі обмеження. В іншому випадку вам може знадобитися звернутися до їх підтримки, щоб перевірити, чи існують обмеження щодо надсилання електронних листів.

Перевірте папки зі спамом; не допускати позначення листів як спаму

Часто з різних причин електронні листи, що надсилаються через PHP (та інші мови програмування на стороні сервера), потрапляють у папку спаму одержувача. Завжди перевіряйте там, перш ніж усунути проблеми з кодом.

Щоб уникнути пошти, надісланої через PHP, до папки спаму одержувача, ви можете зробити різні дії, як у своєму PHP-коді, так і в іншому випадку, щоб мінімізувати ймовірність того, що ваші електронні листи будуть позначені як спам. Хороші поради від Міхель де Маре включають:

  • Використовуйте методи аутентифікації електронної пошти, такі як SPF та DKIM, щоб довести, що ваші електронні листи та ваше доменне ім’я належать разом, і щоб запобігти підробленню вашого доменного імені. Веб-сайт SPF включає майстра для генерування інформації про DNS для вашого сайту.
  • Перевірте свою зворотну DNS, щоб переконатися, що IP-адреса вашого поштового сервера вказує на доменне ім’я, яке ви використовуєте для надсилання пошти.
  • Переконайтеся, що IP-адресу, яку ви використовуєте, немає у чорному списку
  • Переконайтеся, що адреса відповіді - дійсна, існуюча адреса.
  • Використовуйте повне справжнє ім’я адресата в полі Ко, а не лише адресу електронної пошти (наприклад "John Smith" <john@blacksmiths-international.com>).
  • Контролюйте свої облікові записи, такі як abuse@yourdomain.com та postmaster@yourdomain.com. Це означає - переконайтеся, що ці облікові записи існують, прочитайте, що їм надсилається, і дійте за скаргами.
  • І, нарешті, зробити це дуже легко відмовитися від підписки. В іншому випадку ваші користувачі скасують підписку, натиснувши кнопку спаму , і це вплине на вашу репутацію.

Див. Як ви переконаєтесь, що електронний лист, який ви надсилаєте програмно, не позначається автоматично як спам? детальніше з цієї теми.

Переконайтеся, що всі заголовки пошти надані

Деякі програми для спаму будуть відхиляти пошту, якщо в ній відсутні загальні заголовки, такі як "Від" та "Відповісти до":

$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);

Переконайтесь, що в заголовках пошти немає синтаксичних помилок

Недійсні заголовки такі ж погані, як і відсутність заголовків. Один неправильний символ може бути всього, що потрібно, щоб зірвати вашу електронну пошту. Двічі перевірте, щоб переконатися, що ваш синтаксис правильний, оскільки PHP не спричинить ці помилки для вас.

$headers = array("From from@example.com", // missing colon
    "Reply To: replyto@example.com",      // missing hyphen
    "X-Mailer: "PHP"/" . PHP_VERSION      // bad quotes
);

Не використовуйте підроблений From:відправник

Хоча в пошті має бути відправник від: Ви можете не просто використовувати якесь значення. Зокрема, адреси відправника, надіслані користувачем, є надійним способом заблокувати пошту:

$headers = array("From: $_POST[contactform_sender_email]"); // No!

Причина: ваш веб-сервер або поштовий сервер не має списку SPF / DKIM, щоб претендувати на відповідальність за адреси @hotmail або @gmail. Він може навіть мовчки скидати пошту з From:доменами відправника, для яких не налаштовано.

Переконайтесь, що значення одержувача правильне

Іноді проблема настільки проста, як неправильне значення для одержувача електронної пошти. Це може бути пов’язано з використанням неправильної змінної.

$to = 'user@example.com';
// other variables ....
mail($recipient, $subject, $message, $headers); // $recipient should be $to

Інший спосіб перевірити це - жорсткий код значення одержувача у mail()виклик функції:

mail('user@example.com', $subject, $message, $headers); 

Це може стосуватися всіх mail()параметрів.

Надіслати на кілька облікових записів

Щоб усунути проблеми з обліковим записом електронної пошти, надішліть електронну пошту на кілька облікових записів електронної пошти у різних постачальників електронної пошти . Якщо ваші електронні листи не надходять до облікового запису Gmail, надсилайте ті самі електронні листи до облікових записів Yahoo, Hotmail і звичайного облікового запису POP3 (як-от ваш електронний рахунок, наданий провайдером).

Якщо електронні листи надходять до всіх або інших облікових записів електронної пошти, ви знаєте, що ваш код надсилає електронні листи, але ймовірно, що постачальник облікових записів електронної пошти блокує їх з якихось причин. Якщо електронний лист не надходить до жодного облікового запису електронної пошти, швидше за все, проблема буде пов’язана з вашим кодом.

Переконайтесь, що код відповідає методу форми

Якщо ви встановили метод форми POST, переконайтеся, що використовуєте $_POSTдля пошуку значень форми. Якщо ви встановили його GETвзагалі або не встановили, переконайтесь, що ви $_GETшукаєте значення форми.

Переконайтесь, що actionзначення форми вказує на правильне розташування

Переконайтеся, що actionатрибут форми містить значення, яке вказує на ваш поштовий код PHP.

<form action="send_email.php" method="POST">

Переконайтеся, що веб-хост підтримує надсилання електронної пошти

Деякі провайдери веб-хостингу не дозволяють і не дозволяють надсилати електронні листи через свої сервери. Причини цього можуть бути різними, але якщо вони відключили відправлення пошти, вам потрібно буде використовувати альтернативний метод, який використовує третю сторону для надсилання цих листів для вас.

Електронний лист до їх технічної підтримки (після поїздки до їхньої онлайн-підтримки або поширених запитань) повинен уточнити, чи є можливості електронної пошти доступні на вашому сервері.

Переконайтеся, що localhostпоштовий сервер налаштований

Якщо ви розробляєте локальну робочу станцію за допомогою WAMP, MAMP або XAMPP, сервер електронної пошти, ймовірно, не встановлений на вашій робочій станції. Без цього PHP не може надсилати пошту за замовчуванням.

Ви можете подолати це, встановивши базовий поштовий сервер. Для Windows ви можете скористатися безкоштовною Mercury Mail .

Ви також можете використовувати SMTP для надсилання електронної пошти. Дивіться цю чудову відповідь від Vikas Dwivedi, щоб дізнатися, як це зробити.

Увімкніть користувальницький PHP mail.log

Окрім файлу журналу MTA та PHP, ви можете увімкнути ведення журналу для цієї mail()функції спеціально. Він не записує повну взаємодію SMTP, але принаймні функціональні параметри виклику та сценарій виклику.

ini_set("mail.log", "/tmp/mail.log");
ini_set("mail.add_x_header", TRUE);

Докладні відомості див. У розділі http://php.net/manual/en/mail.configuration.php . (Найкраще , щоб включити ці параметри в php.iniабо .user.iniабо .htaccessможливо.)

Зверніться до служби тестування пошти

Існують різні служби доставки та перевірки спаму, які ви можете використовувати для тестування налаштувань MTA / веб-сервера. Зазвичай ви надсилаєте поштовий зонд на адресу: їх адресу, потім отримуєте звіт про доставку та більш конкретні збої чи аналізи пізніше:

Використовуйте іншу пошту

Вбудована mail()функція PHP зручна і часто виконує роботу, але у неї є свої недоліки . На щастя, є альтернативи, які пропонують більшу потужність та гнучкість, включаючи вирішення багатьох питань, описаних вище:

Все це може поєднуватися з професійним SMTP-сервером / постачальником послуг. (Оскільки типові плани 08/15 для спільного веб-хостингу потрапляють або пропускають, коли мова заходить про налаштування / налаштування електронної пошти.)


11
Добре написано, Джон. Я хотів би лише додати ще одне: перевірка журналів поштового сервера поштового сервера (будь то локальний або віддалений хост), якщо це можливо, часто може пролити світло на те, що викликає проблему. Ці журнали повинні показувати, 1) чи було повідомлення отримано від скрипту PHP сервером поштового відправлення, і якщо так, 2) чи приймає MX приймаючу доставку з поштового сервера.
mti2935

@ mti2935 Це так корисно, що я здивований, що пропустив це. Я обов'язково додаю це незабаром. :)
Джон Конде

1
я б почав з використання mail(), не

1
той же веб-сайт на 000webhost успішно і швидко надсилає електронні листи на домен netai.net, але на сайті88.net у мене той самий веб-сайт, що я отримую в консолі, яку повідомлення надсилає успішно, але я не отримую жодних повідомлень. Також у домені comuf.com я отримую помилку. (Той самий веб-сайт того ж хоста працює лише на домені netai.net, також працює net16.net)
Nicolas Papaconstantinou,

1
моє запитання ( stackoverflow.com/questions/44866673/… ) було позначене як дублікат цього, але я досі не можу його зрозуміти. Будь-які пропозиції?
Захарій Елкінс

37

Додайте заголовок пошти у функцію пошти:

$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>';
}

25
  1. Завжди намагайтеся надсилати заголовки у функції пошти.
  2. Якщо ви надсилаєте пошту через localhost, виконайте настройки SMTP для надсилання пошти.
  3. Якщо ви надсилаєте пошту через сервер, перевірте, чи функція надсилання електронної пошти включена на вашому сервері.

20

Якщо ви використовуєте конфігурацію SMTP для надсилання електронної пошти, спробуйте використовувати PHPMailer замість цього. Ви можете завантажити бібліотеку з https://github.com/PHPMailer/PHPMailer .

Я створив електронний лист таким чином:

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";
}

2
Мені також довелося користуватися: requ ("phpmailer / class.smtp.php");
Дуг

15

Перш ніж надсилати пошту, додайте заголовки:

<?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);

І ще одне. mail()Функція не працює в локальному хості. Завантажте свій код на сервер і спробуйте.


1
це фактично змусило форму надсилати - моє запитання зараз буде ... як я показую користувачеві, набраному електронною поштою, тепер, коли я замінив його заголовком ...
user3818620

чи запобіжить це пошта зі спам-папки. Я бачив, якщо ми надсилаємо пошту більше 10, використовуючи цей метод, який ви використовували у своєму коді gmail, надішліть цю пошту спаму.
Jewhuq

У ОП є такий рядок: $from = 'From: yoursite.com'; який не схожий на повну дійсну адресу електронної пошти, немає локальної частини. Ви замінили заголовок From і додали додаткові. А точніше $fromсказане вище у вашому прикладі. Неправильне формування, ймовірно, було початковою проблемою ОП.
Прогрок

13

Це працювало для мене на 000webhost, виконуючи наступні дії:

$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";

Під час надсилання електронної пошти введіть безпосередньо електронну адресу:

mail('email@gmail.com', $subject, $message, $headers)

Використовуйте ''і ні "".

Цей код працює, але електронний лист отримано з півгодинним запізненням.


10

Здебільшого mail()функція відключена у спільному хостингу. Кращий варіант - використовувати SMTP. Найкращим варіантом буде Gmail або 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();
}
?>

Це хороша ідея зберегти smtp користувача та пароль у простому тексті на сервері?
Юрі

@Juri, мабуть, немає ... Боже, я не можу зрозуміти, як змусити роботу функції пошти:. (

9

Якщо ви використовуєте лише цю mail()функцію, вам потрібно доповнити файл конфігурації.

Вам потрібно відкрити розширення пошти, встановити SMTP smtp_portі так далі, і найголовніше - ваше ім’я користувача та пароль. Без цього пошти не можна надсилати. Також ви можете використовувати PHPMailклас для надсилання.


9

Спробуйте ці дві речі окремо та разом:

  1. видалити if($_POST['submit']){}
  2. видалити $from(тільки моя кишка)

8

Я думаю, що це повинно зробити трюк. Я щойно додав if(issetі додав конкатенацію змінним у тілі, щоб відокремити PHP від ​​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>'; 
    }
}

?>

8

Тим, хто вважає, що це йде вперед, я б не рекомендував використовувати mail. Є кілька відповідей, які стосуються цього, але не причини цього.

mailФункція PHP не тільки непрозора, вона повністю покладається на будь-який MTA, який ви використовуєте (тобто Sendmail ) для виконання роботи. mailбуде тільки сказати вам , якщо АПС не зміг прийняти його (тобто Sendmail був вниз , коли ви намагалися відправити). Він не може сказати вам, чи надійшла пошта, оскільки її передали. Як така (як відомості відповіді Джона Конде ), ви тепер зможете поспілкуватися з журналами MTA і сподіваєтесь, що вона вам достатньо розповість про невдачу виправити. Якщо ви перебуваєте на спільному хості або не маєте доступу до журналів MTA, вам не пощастить. На жаль, за замовчуванням для більшості встановлень ванілі для Linux обробляють це таким чином.

Бібліотека пошти ( PHPMailer , Zend Framework 2+ та ін.) Робить щось дуже відмінне від mail. Вони відкривають сокет безпосередньо на поштовому сервері, що приймає, а потім надсилають команди SMTP пошти безпосередньо через цей сокет. Іншими словами, клас діє як власний MTA (зауважте, що ви можете сказати бібліотекам, щоб mailв кінцевому рахунку відправити пошту, але я настійно рекомендую вам цього не робити).

Це означає, що ви можете безпосередньо бачити відповіді з приймаючого сервера (наприклад, у PHPMailer можна включити вихід налагодження ). Більше не здогадуйтесь, чи не вдалося надіслати пошту чи чому.

Якщо ви використовуєте SMTP (тобто ви телефонуєте isSMTP()), ви можете отримати детальну стенограму розмови SMTP, використовуючи SMTPDebugвластивість.

Встановіть цю опцію, включивши у свій сценарій такий рядок:

$mail->SMTPDebug = 2;

Ви також отримаєте перевагу кращого інтерфейсу. З mailви повинні налаштувати всі заголовки, додаток і т.д. З бібліотекою, є спеціальна функція , щоб зробити це. Це також означає, що функція виконує всі складні частини (як заголовки).


6
$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>";
}

6

Ви можете використовувати конфігураційну електронну пошту від CodeIgniter . Наприклад, за допомогою SMTP (простий спосіб):

$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
}

Це працює для мене!


1
fsockopen () [function.fsockopen]: php_network_getaddresses: getaddrinfo не вдалося: Такого хоста не відомо. - Якщо я зіткнувся з цією помилкою, то в чому причина і що потрібно зробити?
Чудхурі Саадман Махмід

1
"Працює для мене" - це лише анекдотична інформація, але насправді не так багато пояснень. Пароль для порту та smtp був би введеним в оману для більшості користувачів.
Маріо

Що таке "налаштування електронної пошти" ? У вас є довідник?
Пітер Мортенсен

4

Спробуйте це

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>
        '; 
    }
}

4

Можливо, проблема полягає в конфігурації поштового сервера. Щоб уникнути подібних проблем або не потрібно турбуватися про проблему поштового сервера, рекомендую скористатися PHPMailer .

Це плагін, у якому є все необхідне для надсилання пошти, і єдине, що вам потрібно враховувати, - це включення SMTP-порту (порт: 25 і 465).

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;
}

1
IANA замінив порт 465 на порт 587. Це порт для надсилання пошти за замовчуванням. Коли клієнт електронної пошти або сервер, що надходить, подає електронну пошту для перенаправлення належним поштовим сервером, він завжди повинен використовувати порт 587 SMTP як порт за замовчуванням. Див. Mailgun.com/blog/which-smtp-port-understanding-ports-25-465-587 . Мудра порада: не відкривайте порти на своєму комп’ютері, якщо ви не повністю знаєте, що робите!
Шкода

3

Переконайтеся, що на вашому сервері встановлено Sendmail.

Якщо ви перевірили свій код і переконалися, що там нічого поганого, перейдіть до / var / mail і перевірте, чи порожня ця папка.

Якщо він порожній, вам потрібно буде зробити:

sudo apt-get install sendmail

якщо ви перебуваєте на сервері Ubuntu.


Це занадто грубо, щоб бути корисним. Просто встановлення MTA рідко дозволить дістатися до нього. І повний посібник із налаштування sendmail / postfix / qmail тут буде поза темою.
Маріо

Чи цей коментар посилається на мою відповідь? Тому що цього не сталося зі мною, і я не вирішив це так само точно. Існують різні можливі відповіді на питання, я був одним з них після того, як спробував усе вищезазначене в минулому, моя відповідь вирішив проблему для мене, тому я запропонував це тут як ще одне потенційне рішення.
Даніель

Так, звичайно. Це одна з багатьох можливих відповідей. Однак це все ще спосіб поверхового ІМО. Узагальнюючи його на "вам потрібен MTA", наприклад ...
Маріо

3

Перш за все, у вас може бути занадто багато параметрів для функції mail () ... Ви можете мати максимум п'ять, mail(to, subject, message, headers, parameters);

Що стосується $fromзмінної, вона автоматично надходить з вашого веб-хоста, якщо ви використовуєте Linux cPanel . Він автоматично надходить з вашого імені користувача cPanel та IP-адреси.

$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";

Також переконайтеся, що ви маєте правильний порядок змінних у вашій пошті () функції.

У mail($to, $subject, $message, etc.)тому порядку, інакше є ймовірність, що він не працює.


3

Якщо у вас виникають проблеми з надсиланням електронної пошти з PHP, розгляньте альтернативне подібне PHPMailer або SwiftMailer .

Зазвичай я використовую SwiftMailer всякий раз, коли мені потрібно надсилати пошту з PHP.


Основне використання:

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);
}

Дивіться офіційну документацію для отримання додаткової інформації про використання SwiftMailer.


3

Для тих, хто не хоче користуватися зовнішніми поштовими повідомленнями та хоче відправити пошту () на спеціалізований сервер Linux.

Спосіб, як PHP надсилає пошту, описаний php.iniу розділі[mail function] .

Параметр sendmail-pathописує, як викликається sendmail. Значенням за замовчуванням є sendmail -t -i, тому якщо ви отримаєте працюючу sendmail -t -i < message.txtв консолі Linux - ви будете готові. Ви також можете додатиmail.log до налагодження і бути впевненим, що пошта () дійсно викликається.

Різні MTA можуть впроваджувати sendmail. Вони просто роблять символічне посилання на свої бінарні файли щодо цього імені. Наприклад, у Debian за замовчуванням - Postfix . Налаштуйте свій MTA для надсилання пошти та випробування з консолі за допомогою sendmail -v -t -i < message.txt. Файл message.txtповинен містити всі заголовки повідомлення та тіло, адреса призначення конверта буде взята із To:заголовка. Приклад:

From: myapp@example.com
To: mymail@example.com
Subject: Test mail via sendmail.

Text body.

Я вважаю за краще використовувати ssmtp як MTA, оскільки він простий і не вимагає запуску демона з відкритими портами. ssmtp підходить лише для надсилання пошти з localhost . Він також може надсилати аутентифіковану електронну пошту через ваш рахунок на службі загальнодоступної пошти. Встановіть ssmtp та відредагуйте файл конфігурації /etc/ssmtp/ssmtp.conf. Для того, щоб також можна було отримувати локальну системну пошту до облікових записів Unix (наприклад, сповіщення про викорінення завдань Cron)/etc/ssmtp/revaliases файл.

Ось моя конфігурація для мого облікового запису на пошті Яндекс:

root=mymail@example.com
mailhub=smtp.yandex.ru:465
FromLineOverride=YES
UseTLS=YES
AuthUser=abcde@yandex.ru
AuthPass=password

2

Це торкнеться лише невеликої кількості користувачів, але я хотів би, щоб це було задокументовано для цієї невеликої жменьки. Цей член цієї маленької жменьки витратив 6 годин на усунення робочого скрипта PHP через цю проблему.

Якщо ви збираєтесь в університет, який працює з XAMPP від ​​www.AceITLab.com, ви повинні знати, що наш професор нам не сказав: Брандмауер AceITLab (не брандмауер Windows) блокує MercuryMail у XAMPP. Вам доведеться використовувати альтернативний поштовий клієнт, груша працює на нас. Вам доведеться надіслати обліковий запис Gmail із низькими налаштуваннями безпеки.

Так, я знаю, це абсолютно марно для електронної пошти в реальному світі. Однак, з того, що я бачив, академічні установки та реальний світ часто мають дорогоцінне мало спільного.


Це занадто дивно специфічно і дійсно нікому не допоможе. Будь ласка, скористайтеся посиланням [delete] під своєю відповіддю.
Маріо

Що в цьому контексті "груша"? Ви маєте на увазі PEAR , сховище програмного забезпечення PHP? Або щось інше? Наприклад, однолітка ?
Пітер Мортенсен

Ви справді маєте на увазі «дорогоцінну маленьку» ? Чи чогось бажати? Чому?
Пітер Мортенсен

1

Якщо ви використовуєте цей код на локальному сервері (тобто на своєму комп’ютері для цілей розвитку), він не надсилатиме електронний лист одержувачу. Це створить .txtфайл у папці з назвоюmailoutput .

У тому випадку, якщо ви користуєтеся послугою безкоштовного шлангу, наприклад, 000webhostабо hostinger, ці постачальники послуг відключаютьmail() функцію, щоб запобігти випадковому використанню підробки електронної пошти, спаму тощо.

Якщо ви впевнені, що постачальник послуг підтримує функцію mail (), ви можете перевірити цей посібник PHP для подальшої довідки,

PHP пошта ()

Щоб перевірити погоду, що служба хостингу підтримує функцію mail (), спробуйте запустити цей код (не забудьте змінити електронну адресу одержувача) :

<?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);
?>

1

Установка Sendmail для Debian 10.0.0 ("Buster") насправді була тривіальною!

php.ini

[mail function]
sendmail_path=/usr/sbin/sendmail -t -i
; (Other directives are mostly windows)

Стандартна установка пакету sendmail (що дозволяє "надіслати"):

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

Різні корисні команди:

which sendmail                              # /usr/sbin/sendmail
which sendmailconfig                        # /usr/sbin/sendmailconfig
man sendmail                                # Documentation
systemctl restart sendmail                  # As and when required

Підтвердження (можливість відправки)

echo "Subject: sendmail test" | sendmail -v <yourEmail>@gmail.com

Сказане зайняло близько 5 хвилин. Тоді я витратив 5 годин ... Не забудьте перевірити свою папку зі спамом !


0

Є кілька можливостей:

  1. Ви зіткнулися з проблемою сервера. На сервері немає жодного поштового сервера. Таким чином, ваша пошта не працює, оскільки ваш код нормальний, а пошта працює з типом.

  2. Ви не отримуєте розміщене значення. Спробуйте свій код зі статичним значенням.

  3. Використовуйте SMTP-пошти для надсилання пошти ...


0

Ви можете використовувати libmail: http://lwest.free.fr/doc/php/lib/index.php3?page=mail&lang=en

include "libmail.php";
$m = new Mail(); // Create the mail
$m->From($_POST['form']);
$m->To($_POST['to']);
$m->Subject($_POST['subject']);
$m->Body($_POST['body']);
$m->Cc($_POST['cc']);
$m->Priority(4);
// Attach a file of type 'image/gif' to be displayed in the message if possible
$m->Attach("/home/leo/toto.gif", "image/gif", "inline");
$m->Send(); // Send the mail
echo "Mail was sent:"
echo $m->Get(); // Show the mail source

5
Важливо зазначити: це лише mail()обгортка функцій. Лише додається побудова повідомлень та деякі трюки.
Маріо

0

Ви можете бачити свої помилки:

error_reporting(E_ALL);

І мій зразок коду:

<?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';
?>

1
SMTPDebug = 0не корисно. Також звичайний "пароль" не може працювати з GMail. Ця відповідь не дуже сприяє.
Маріо

-2

Якщо ваша система sendmail працює, ваш код потрібно змінити таким чином:

<?php
    $name = $_POST['name'];
    $email = $_POST['email'];
    $message = $_POST['message'];

    $header ="
Content-Type: text/html; charset=UTF-8\r\n
MIME-Version: 1.0\r\n
From: \"$name\" <$email>\r\n
Reply-To: no-reply@yoursite.com\r\n
X-Mailer: yoursite.com mailer\r\n
";

    $to = '"Contact" <contact@yoursite.com>'; 
    $subject = 'Customer Inquiry';
    $body =<<<EOB
<!DOCTYPE html>
<html>
    <body>
        $message
    </body>
</html>
EOB;

    if ($_POST['submit']) {
        if (mail ($to, $subject, $body, $header) !== false) { 
            echo '<p>Your message has been sent!</p>';
        } else { 
            echo '<p>Something went wrong, go back and try again!</p>'; 
        }
    }
?>

Це дає змогу надсилати електронну пошту на основі HTML.

Цікавий інтерес:

  1. ми побудували рядок мультиліній заголовка (кожен рядок розділений \ r \ n);
  2. ми додали тип вмісту, щоб виразити, ми повертаємо HTML, щоб ви могли складати кращі електронні листи (ви можете додати до свого повідомлення HTML-код, який ви хочете, включаючи CSS, як і на сторінці HTML).

Примітка: <<<EOBсинтаксис вимагає, щоб останній маркер EOB починався з початку pf рядка і не має пробілу або будь-якого символу після крапки з комою.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.