簡體   English   中英

PHP 郵件 function 沒有完成郵件發送

[英]PHP mail function doesn't complete sending of e-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";

    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 代碼。 代碼完美提交,但從未發送 email。我該如何解決這個問題?

盡管此答案的某些部分僅適用於mail()函數本身的使用,但其中許多故障排除步驟可以應用於任何 PHP 郵件系統。

您的腳本似乎沒有發送電子郵件有多種原因。 除非有明顯的語法錯誤,否則很難診斷這些事情。 如果沒有,您需要通過下面的清單來查找您可能遇到的任何潛在陷阱。

確保啟用錯誤報告並設置為報告所有錯誤

錯誤報告對於根除代碼中的錯誤和 PHP 遇到的一般錯誤至關重要。 需要啟用錯誤報告才能接收這些錯誤。 將以下代碼放在 PHP 文件的頂部(或主配置文件中)將啟用錯誤報告。

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

請參閱如何在 PHP 中獲得有用的錯誤消息? -這個答案有關此的更多詳細信息。

確保調用了mail()函數

這可能看起來很愚蠢,但一個常見的錯誤是忘記在代碼中實際放置mail()函數。 確保它在那里並且沒有被注釋掉。

確保正確調用了mail()函數

布爾郵件(字符串 $to,字符串 $subject,字符串 $message [,字符串 $additional_headers [,字符串 $additional_parameters ]])

mail 函數接受三個必需的參數,以及可選的第四個和第五個參數。 如果您對mail()的調用沒有至少三個參數,它將失敗。

如果您對mail()的調用沒有正確順序的正確參數,它也會失敗。

檢查服務器的郵件日志

您的 Web 服務器應該記錄通過它發送電子郵件的所有嘗試。 這些日志的位置會有所不同(您可能需要詢問服務器管理員它們的位置),但它們通常可以在用戶的​​根目錄下的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 代碼中或其他方式中執行各種操作,以最大限度地減少您的電子郵件被標記為垃圾郵件的機會。 Michiel de Mare的好建議包括:

  • 使用電子郵件認證方法,例如SPFDKIM來證明您的電子郵件和您的域名屬於同一個,並防止您的域名被欺騙。 SPF 網站包含一個為您的站點生成 DNS 信息的向導。
  • 檢查您的反向 DNS以確保您的郵件服務器的 IP 地址指向您用於發送郵件的域名。
  • 確保您使用的 IP 地址不在黑名單上
  • 確保回復地址是有效的現有地址。
  • 在“收件人”字段中使用收件人的完整真實姓名,而不僅僅是電子郵件地址(例如"John Smith" <john@blacksmiths-international.com> )。
  • 監控您的濫用帳戶,例如abuse@yourdomain.examplepostmaster@yourdomain.example 這意味着 - 確保這些帳戶存在,閱讀發送給他們的內容,並對投訴采取行動。
  • 最后,讓退訂變得非常容易。 否則,您的用戶將通過按垃圾郵件按鈕取消訂閱,這將影響您的聲譽。

請參閱如何確保以編程方式發送的電子郵件不會被自動標記為垃圾郵件? 有關此主題的更多信息。

確保提供所有郵件標題

如果郵件缺少常見的標頭,例如“From”和“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);

確保郵件標頭沒有語法錯誤

無效的標頭與沒有標頭一樣糟糕。 一個不正確的字符可能會導致您的電子郵件脫軌。 仔細檢查以確保您的語法正確,因為 PHP不會為您捕獲這些錯誤。

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

不要使用虛假From: sender

雖然郵件必須有 From: 發件人,但您不能只使用任何值。 特別是用戶提供的發件人地址是阻止郵件的可靠方法:

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

原因:您的 Web 或發送郵件服務器未列入 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 帳戶(如您的 ISP 提供的電子郵件帳戶)。

如果電子郵件到達所有或部分其他電子郵件帳戶,則您知道您的代碼正在發送電子郵件,但電子郵件帳戶提供商可能出於某種原因阻止了它們。 如果電子郵件未到達任何電子郵件帳戶,則問題很可能與您的代碼有關。

確保代碼與表單方法匹配

如果您已將表單方法設置為POST ,請確保您使用$_POST來查找表單值。 如果您已將其設置為GET或根本沒有設置,請確保您使用$_GET來查找您的表單值。

確保您的表單action值指向正確的位置

確保您的表單action屬性包含一個指向您的 PHP 郵件代碼的值。

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

確保 Web 主機支持發送電子郵件

一些 Web 托管服務提供商不允許或啟用通過其服務器發送電子郵件。 原因可能會有所不同,但如果他們禁用了郵件發送,您將需要使用另一種方法,即使用第三方為您發送這些電子郵件。

發給他們技術支持的電子郵件(在訪問他們的在線支持或常見問題解答之后)應該說明您的服務器上是否有電子郵件功能。

確保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/網絡服務器設置。 通常,您將郵件探測發送到:他們的地址,然后獲取交付報告和更具體的失敗或分析:

使用不同的郵件程序

PHP 的內置mail()函數很方便,經常可以完成工作,但它也有缺點 幸運的是,有一些替代方案可以提供更多的功能和靈活性,包括處理上述許多問題:

所有這些都可以與專業的 SMTP 服務器/服務提供商結合使用。 (因為在電子郵件設置/配置方面,典型的 08/15 共享虛擬主機計划會受到影響。)

在郵件函數中添加郵件頭:

$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>';
}
  1. 始終嘗試在郵件功能中發送標頭。
  2. 如果您通過 localhost 發送郵件,請進行 SMTP 設置以發送郵件。
  3. 如果您通過服務器發送郵件,請檢查您的服務器上是否啟用了電子郵件發送功能。

如果您使用 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";
}

在發送郵件之前添加一些標題:

<?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()函數在本地主機中不起作用。 將您的代碼上傳到服務器並嘗試。

通過執行以下操作,它在 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)

使用''而不是""

此代碼有效,但收到電子郵件時延遲了半小時。

大多數情況下,共享主機中禁用了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;
    } 
}
?>

聯系電子郵件.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();
}
?>

如果只使用mail()函數,則需要完成配置文件。

您需要打開郵件擴展,設置SMTP smtp_port等,最重要的是您的用戶名和密碼。 沒有它,郵件就無法發送。 此外,您可以使用PHPMail類發送。

分別和一起嘗試這兩件事:

  1. 刪除if($_POST['submit']){}
  2. $from

我認為這應該可以解決問題。 我剛剛添加了一個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>'; 
    }
}

?>

對於任何發現這種情況的人,我不建議使用mail 有一些答案涉及到這一點,但不是為什么

PHP 的mail功能不僅不透明,它完全依賴於您使用的任何MTA (即Sendmail )來完成工作。 mail只會告訴您 MTA 是否無法接受它(即,當您嘗試發送時,Sendmail 已關閉)。 它無法告訴您郵件是否成功,因為它已將其發送出去。 因此(如John Conde 的回答詳細信息),您現在可以擺弄 MTA 的日志,並希望它能告訴您足夠多的有關無法修復它的信息。 如果您在共享主機上或無權訪問 MTA 日志,那么您就不走運了。 可悲的是,大多數 Linux 香草安裝的默認設置都是這樣處理的。

郵件庫( PHPMailer 、Zend Framework 2+ 等)與mail有很大不同。 他們直接打開一個到接收郵件服務器的套接字,然后直接通過該套接字發送 SMTP 郵件命令。 換句話說,該類充當它自己的 MTA(請注意,您可以告訴庫使用mail最終發送郵件,但我強烈建議您不要這樣做)。

這意味着您可以直接看到來自接收服務器的響應(例如,在 PHPMailer 中,您可以打開調試輸出)。 不再猜測郵件是否發送失敗或原因。

如果您正在使用 SMTP(即您正在調用isSMTP() ),您可以使用SMTPDebug屬性獲取 SMTP 對話的詳細記錄。

通過在腳本中包含這樣的行來設置此選項:

 $mail->SMTPDebug = 2;

您還可以從更好的界面中受益。 對於mail ,您必須設置所有標題、附件等。對於庫,您有一個專門的功能來做到這一點。 這也意味着該函數正在處理所有棘手的部分(如標題)。

您可以使用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
}

這個對我有用!

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

嘗試這個:

<?php
    $to = "somebody@example.com, somebodyelse@example.com";
    $subject = "HTML email";

    $message = "
        <html>
        <head>
           <title>HTML email</title>
        </head>
        <body>
          <p>This email contains HTML Tags!</p>
          <table>
            <tr>
             <th>Firstname</th>
             <th>Lastname</th>
            </tr>
            <tr>
              <td>John</td>
              <td>Doe</td>
            </tr>
          </table>
        </body>
        </html>";

    // Always set content-type when sending HTML email
    $headers = "MIME-Version: 1.0" . "\r\n";
    $headers .= "Content-type:text/html;charset=UTF-8" . "\r\n";

    // More headers
    $headers .= 'From: <webmaster@example.com>' . "\r\n";
    $headers .= 'Cc: myboss@example.com' . "\r\n";

    mail($to, $subject, $message, $headers);
?>

嘗試這個

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

可能問題出在郵件服務器的配置上。 為避免此類問題或您不必擔心郵件服務器問題,我建議您使用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;
}

首先,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() 函數中的變量順序正確。

mail($to, $subject, $message, etc.)按該順序排列,否則有可能無法正常工作。

如果您在使用 PHP 發送郵件時遇到問題,請考慮使用PHPMailerSwiftMailer 之類的替代方法。

每當我需要使用 PHP 發送郵件時,我通常會使用 SwiftMailer。


基本用法:

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 的更多信息,請參閱官方文檔

這只會影響一小部分用戶,但我希望為那一小部分用戶記錄下來。 由於這個問題,一小撮人中的這個成員花費了 6 個小時對一個工作的 PHP 郵件腳本進行故障排除。

如果你要去一所運行來自 www.AceITLab.com 的 XAMPP 的大學,你應該知道我們的教授沒有告訴我們的:AceITLab 防火牆(不是 Windows 防火牆)在 XAMPP 中阻止 MercuryMail。 您必須使用替代郵件客戶端,pear 正在為我們工作。 您必須發送到安全設置較低的 Gmail 帳戶。

是的,我知道,這對於現實世界的電子郵件完全沒用。 然而,據我所見,學術環境和現實世界往往沒有什么共同之處。

對於那些不想使用外部郵件程序並希望在專用 Linux 服務器上發送 mail() 的人。

PHP 發送郵件的方式在[mail function]部分的php.ini中進行了描述。

參數sendmail-path描述了 sendmail 是如何被調用的。 默認值是sendmail -t -i ,所以如果你在 Linux 控制台中得到一個工作的sendmail -t -i < message.txt - 你就完成了。 您還可以添加mail.log進行調試,並確保確實調用了 mail()。

不同的 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 作業向 root 發出警報)配置/etc/ssmtp/revaliases文件。

這是我在 Yandex 郵件上的帳戶配置:

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

確保您的服務器中安裝了 Sendmail。

如果您檢查了代碼並確認那里沒有問題,請轉到 /var/mail 並檢查該文件夾是否為空。

如果它是空的,您將需要執行以下操作:

sudo apt-get install sendmail

如果您在 Ubuntu 服務器上。

Debian 10.0.0 ('Buster') 的Sendmail安裝實際上很簡單!

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 個小時……別忘了檢查你的垃圾郵件文件夾

如果您在本地服務器(即用於開發目的的計算機)上運行此代碼,它不會將電子郵件發送給收件人。 它將在名為mailoutput的文件夾中創建一個.txt文件。

如果您使用免費的托管服務,例如000webhosthostinger ,這些服務提供商會禁用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);
?>

您可以使用PHPMailer ,它可以完美運行,這是一個代碼示例:

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

您可以使用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

您可以通過以下方式查看錯誤:

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

如果您對托管在 Hostgator 上的應用程序感到困惑,就是解決我的問題的方法。 非常感謝發布詳細解決方案的人。 萬一有一天鏈接掉線了,你有總結:

  • 在您的服務器中查找 sendmail 路徑。 一個簡單的檢查方法是在一個只有你可以訪問的頁面中臨時編寫以下代碼,以讀取生成的信息: <?php phpinfo(); ?> <?php phpinfo(); ?> . 打開此頁面,然后查找sendmail path (然后,不要忘記刪除此代碼!)
  • 問題和修復:如果您的 sendmail 路徑只顯示-t -i ,則編輯服務器的php.ini並添加以下行: sendmail_path = /usr/sbin/sendmail -t -i;

但是,在能夠使用 PHP mail()函數發送郵件后,我了解到它發送的是未經身份驗證的電子郵件,這又造成了另一個問題。 郵件都掉進了我Hotmail的垃圾郵箱里,有些郵件從來沒有送過,我想這與他們沒有經過身份驗證有關。 畢竟,這就是為什么我決定使用 SMTP 從mail()切換到PHPMailer

這部分 $headers 中的“From:”$email 地址可能有問題:

From: \"$name\" <$email>

要試用它,請發送一封不帶標題部分的電子郵件,例如:

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

如果是這種情況,請嘗試使用已在您嘗試發送郵件的系統上創建的電子郵件帳戶。

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

發送 HTML 電子郵件發送電子郵件時,您可以指定 Mime 版本、內容類型和字符集以發送 HTML 電子郵件。

示例上面的示例將向 name@example.com 發送 HTML 電子郵件消息。 您可以對這個程序進行編碼,使其接收用戶的所有內容,然后發送電子郵件。

為我解決了這個問題的是某些提供商在使用 php 郵件時不允許外部收件人:

將代碼中的收件人($recipient)更改為本地收件人。 這意味着使用來自服務器域的電子郵件地址,例如,如果您的服務器域是www.yourdomain.com ,那么收件人的電子郵件應該是某人@yourdomain.com。 上傳修改后的php文件並重試。 如果它仍然不起作用:將發件人 ($sender) 更改為本地電子郵件(使用與收件人相同的電子郵件)。 上傳修改后的php文件並重試。

希望這會有所幫助! https://www.arclab.com/en/kb/php/how-to-test-and-fix-php-mail-function.html

我遇到了這個問題,發現剝離標題有助於我將郵件發送出去。 所以這:

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

變成了這樣:

$headers = "From: ".__SITE_TITLE."\r\n";
$headers .= "Reply-To: ".$sender."\r\n";

不需要 To: 標頭。

郵件客戶端非常擅長嗅探 URL 並將它們重寫為超鏈接。 所以我沒有費心編寫 HTML 並在 content-type 標頭中指定 text/html。 我只是在消息正文中用 \r\n 拋出了新行。 我很欣賞這不是編碼純粹主義者的方法,但它可以滿足我的需要。

在我的例子中,email 被很好地發送但被接收,因為整個消息在一行中超過 998 個字符。 我需要使用以下行使最大長度為 70 的行: 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.

有幾種可能性:

  1. 您正面臨服務器問題。 該服務器沒有任何郵件服務器。 因此,您的郵件無法正常工作,因為您的代碼很好,並且郵件正在使用類型。

  2. 您沒有獲得發布的價值。 嘗試使用靜態值的代碼。

  3. 使用 SMTP 郵件發送郵件...

對於從 gmail smtp 發送電子郵件和使用 php 郵件功能,首先你必須在本地機器上設置 sendmail,一旦設置就意味着你已經設置了本地 smtp 服務器,然后你就可以從你的帳戶發送電子郵件在您的 sendmail smtp 帳戶中設置,就我而言,我按照https://www.developerfiles.com/how-to-send-emails-from-localhost-mac-os-x-el-capitan/ 中的說明進行操作,並且能夠設置帳戶,

如果您的 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. 我們添加了 Content-type 來表達我們返回 HTML 以便您可以撰寫更好的電子郵件(您可以像在 HTML 頁面中那樣在您的消息中添加任何您想要的 HTML 代碼,包括 CSS)。

注意: <<<EOB語法要求最后一個 EOB 標記作為行的開頭,並且在分號之后沒有空格或任何字符。

如果您使用的是PHP郵件程序,則可以使用以下代碼。 只需復制粘貼,然后將***替換為您的數據和憑據即可。 並更改輸入數據名稱的值。

<?php
    require_once ("PHPMailer/PHPMailerAutoload.php");

    $error = array();

    //var_dump($_POST);

    $message = $_POST['a'] . '<br>';
    $message.= $_POST['b'] . '<br>';
    $message.= $_POST['c'] . '<br>';
    $message.= $_POST['d'] . '<br>';
    $message.= $_POST['e'] . '<br>';
    $message.= $_POST['f'] . '<br>';
    $message.= $_POST['g'] . '<br>';
    $message.= $_POST['h'] . '<br>';
    $message.= $_POST['i'] . '<br>';
    $message.= $_POST['j'] . '<br>';
    $message.= $_POST['k'] . '<br>';

    $subject = "Visitor Query";
    $from = "******@******.com"; // example a@b.com
    $password = '******';

    $mail = new PHPMailer();
    $body = $message;
    $mail->IsSMTP();
    $mail->SMTPAuth = true; // Turn on SMTP authentication
    $mail->SMTPKeepAlive = true; // SMTP connection will not close after each email sent, reduces SMTP overhead
    $mail->SMTPDebug = 0;

    //$mail->Host = 'mail.******.com'; // Sets SMTP server
    $mail->Host = 'mail.******.com'; // Sets SMTP server
    $mail->SMTPSecure = 'ssl';
    $mail->Port = 465;
    //$mail->Port = 25;

    $mail->Username = $from; // SMTP username
    $mail->Password = $password; // SMTP password

    $mail->AddAddress ( "******@gmail.com" );
    $mail->AddReplyTo ( "******@gmail.com", "Team");
    $mail->Subject = $subject;
    $mail->Body = $message;
    $mail->From =  $from;
    $mail->FromName = "Visitor's Query";
    $mail->ContentType = "text/html";

    if (count($error == 0)) {

         $mail->Send();

        // echo "_________________wait_______for_______ our _______ reply  !";


    } else {

        echo $error; // Show error messages
        //echo $result;
    }

    //header("location: index.php");
?>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM