La función de correo PHP no completa el envío de correo electrónico


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

He intentado crear un formulario de correo simple. El formulario en sí está en mi index.htmlpágina, pero se envía a una página separada de "gracias por su envío" thankyou.php, donde está incrustado el código PHP anterior. El código se envía perfectamente, pero nunca envía un correo electrónico. ¿Cómo puedo arreglar esto?


2
es su programa en la computadora local o en el host en vivo
Tamil Selvan C

66
1. ¿estás seguro de que no entra en tu spam? 2. ¿tiene sendmail configurado en su casilla?
Steven Moseley

está en un host en vivo, no va a entrar en mi correo no deseado ... no estoy seguro de lo que quieres decir con que sendmail esté configurado en mi casilla, así que supongo que no.
user3818620

intenta enviar sin$from
Artem Ilchenko

Respuestas:


512

Aunque hay partes de esta respuesta que se aplican solo al uso de la mail()función en sí, muchos de estos pasos de solución de problemas se pueden aplicar a cualquier sistema de correo PHP.

Hay una variedad de razones por las cuales su script parece no enviar correos electrónicos. Es difícil diagnosticar estas cosas a menos que haya un error de sintaxis obvio. Sin uno, debe revisar la lista de verificación a continuación para encontrar posibles dificultades que pueda encontrar.

Asegúrese de que el informe de errores esté habilitado y configurado para informar todos los errores

El informe de errores es esencial para eliminar los errores en su código y los errores generales que PHP encuentra. El informe de errores debe estar habilitado para recibir estos errores. Colocar el siguiente código en la parte superior de sus archivos PHP (o en un archivo de configuración maestro) habilitará el informe de errores.

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

Consulte ¿Cómo puedo obtener mensajes de error útiles en PHP? - esta respuesta para más detalles sobre esto.

Asegúrese de que la mail()función se llame

Puede parecer tonto, pero un error común es olvidar colocar la mail()función en su código. Asegúrate de que esté allí y no comentado.

Asegúrese de que la mail()función se llame correctamente

bool mail (cadena $ a, cadena $ asunto, cadena $ mensaje [, cadena $ Additional_headers [, cadena $ Additional_parameters]])

La función de correo toma tres parámetros requeridos y opcionalmente un cuarto y quinto. Si su llamada a mail()no tiene al menos tres parámetros, fallará.

Si su llamada a mail()no tiene los parámetros correctos en el orden correcto, también fallará.

Verifique los registros de correo del servidor

Su servidor web debería estar registrando todos los intentos de enviar correos electrónicos a través de él. La ubicación de estos registros variará (es posible que deba preguntar al administrador del servidor dónde se encuentran), pero comúnmente se pueden encontrar en el directorio raíz de un usuario en logs. Dentro habrá mensajes de error que el servidor informó, si los hay, relacionados con sus intentos de enviar correos electrónicos.

Verifique la falla de conexión del puerto

El bloqueo de puertos es un problema muy común que enfrentan la mayoría de los desarrolladores al integrar su código para entregar correos electrónicos utilizando SMTP. Y esto se puede rastrear fácilmente en los registros de correo del servidor (la ubicación del servidor del registro de correo puede variar de un servidor a otro, como se explicó anteriormente). En caso de que esté en un servidor de alojamiento compartido, los puertos 25 y 587 permanecen bloqueados de forma predeterminada. Este bloqueo ha sido hecho a propósito por su proveedor de alojamiento. Esto es cierto incluso para algunos de los servidores dedicados. Cuando estos puertos estén bloqueados, intente conectarse usando el puerto 2525. Si encuentra que ese puerto también está bloqueado, entonces la única solución es contactar a su proveedor de alojamiento para desbloquear estos puertos.

La mayoría de los proveedores de alojamiento bloquean estos puertos de correo electrónico para proteger su red de enviar correos electrónicos no deseados.

Use los puertos 25 o 587 para conexiones simples / TLS y el puerto 465 para conexiones SSL. Para la mayoría de los usuarios, se sugiere utilizar el puerto 587 para evitar los límites de velocidad establecidos por algunos proveedores de alojamiento.

No use el operador de supresión de errores

Cuando el operador de supresión de errores @ se antepone a una expresión en PHP, cualquier mensaje de error que pueda generar esa expresión se ignorará. Hay circunstancias en las que es necesario usar este operador, pero el envío de correo no es una de ellas.

Si su código contiene @mail(...), puede estar ocultando mensajes de error importantes que lo ayudarán a depurar esto. Elimine @y vea si se informa algún error.

Solo es aconsejable cuando verificaerror_get_last() inmediatamente después de fallas concretas.

Verifique el mail()valor de retorno

La mail()función:

Devuelve TRUEsi el correo fue aceptado con éxito para la entrega, de lo FALSEcontrario. Es importante tener en cuenta que solo porque el correo fue aceptado para la entrega, NO significa que el correo realmente llegará al destino previsto.

Es importante tener en cuenta esto porque:

  • Si recibe un FALSEvalor de devolución, sabe que el error radica en que su servidor acepta su correo. Esto probablemente no sea un problema de codificación, sino un problema de configuración del servidor. Debe hablar con el administrador del sistema para averiguar por qué sucede esto.
  • Si recibe un TRUEvalor de devolución, no significa que su correo electrónico será enviado definitivamente. Simplemente significa que el correo electrónico fue enviado a su controlador respectivo en el servidor con éxito por PHP. Todavía hay más puntos de falla fuera del control de PHP que pueden hacer que el correo electrónico no se envíe.

Por FALSElo tanto, le ayudará a orientarlo en la dirección correcta, TRUEaunque no necesariamente significa que su correo electrónico se haya enviado correctamente. ¡Esto es importante tener en cuenta!

Asegúrese de que su proveedor de alojamiento le permita enviar correos electrónicos y no limite el envío de correos

Muchos servidores web compartidos, especialmente los proveedores de alojamiento web gratuitos, no permiten que se envíen correos electrónicos desde sus servidores o limitan la cantidad que se puede enviar durante un período de tiempo determinado. Esto se debe a sus esfuerzos para limitar el envío de spammers de sus servicios más baratos.

Si cree que su host tiene límites de correo electrónico o bloquea el envío de correos electrónicos, consulte sus Preguntas frecuentes para ver si enumeran dichas limitaciones. De lo contrario, es posible que deba comunicarse con su soporte para verificar si existen restricciones en el envío de correos electrónicos.

Verificar carpetas de spam; evitar que los correos electrónicos se marquen como spam

A menudo, por varias razones, los correos electrónicos enviados a través de PHP (y otros lenguajes de programación del lado del servidor) terminan en la carpeta de correo no deseado del destinatario. Siempre verifique allí antes de solucionar su código.

Para evitar que el correo enviado a través de PHP se envíe a la carpeta de correo no deseado del destinatario, hay varias cosas que puede hacer, tanto en su código PHP como de otro modo, para minimizar las posibilidades de que sus correos electrónicos se marquen como correo no deseado. Los buenos consejos de Michiel de Mare incluyen:

  • Use métodos de autenticación de correo electrónico, como SPF y DKIM para demostrar que sus correos electrónicos y su nombre de dominio pertenecen juntos, y para evitar la falsificación de su nombre de dominio. El sitio web de SPF incluye un asistente para generar la información de DNS para su sitio.
  • Verifique su DNS inverso para asegurarse de que la dirección IP de su servidor de correo apunte al nombre de dominio que utiliza para enviar correo.
  • Asegúrese de que la dirección IP que está utilizando no esté en una lista negra
  • Asegúrese de que la dirección de respuesta sea una dirección válida y existente.
  • Utilice el nombre completo y real del destinatario en el campo Para, no solo la dirección de correo electrónico (p "John Smith" <john@blacksmiths-international.com>. Ej .).
  • Controle sus cuentas de abuso, como abuse@yourdomain.com y postmaster@yourdomain.com. Eso significa: asegúrese de que existan estas cuentas, lea lo que se les envía y actúe sobre las quejas.
  • Finalmente, haga que sea muy fácil darse de baja. De lo contrario, sus usuarios se darán de baja presionando el botón de spam y eso afectará su reputación.

Consulte ¿Cómo se asegura de que el correo electrónico que envía mediante programación no se marque automáticamente como correo no deseado? para más sobre este tema

Asegúrese de que se suministren todos los encabezados de correo

Algunos programas de spam rechazarán el correo si faltan encabezados comunes como "De" y "Responder a":

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

Asegúrese de que los encabezados de correo no tengan errores de sintaxis

Los encabezados inválidos son tan malos como no tener encabezados. Un carácter incorrecto podría ser todo lo que se necesita para descarrilar su correo electrónico. Vuelva a verificar para asegurarse de que su sintaxis sea correcta, ya que PHP no detectará estos errores por usted.

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

No use un From:remitente falso

Si bien el correo debe tener un remitente De, no solo puede usar cualquier valor. En particular, las direcciones de remitente divididas por el usuario son una forma segura de bloquear los correos:

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

Motivo: su servidor de correo web o de envío no está en la lista blanca SPF / DKIM para pretender ser responsable de las direcciones @hotmail o @gmail. Incluso puede soltar silenciosamente correos con From:dominios de remitente para los que no está configurado.

Asegúrese de que el valor del destinatario sea correcto

A veces, el problema es tan simple como tener un valor incorrecto para el destinatario del correo electrónico. Esto puede deberse al uso de una variable incorrecta.

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

Otra forma de probar esto es codificar el valor del destinatario en la mail()llamada de función:

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

Esto puede aplicarse a todos los mail()parámetros.

Enviar a varias cuentas

Para ayudar a descartar problemas con la cuenta de correo electrónico, envíe su correo electrónico a varias cuentas de correo electrónico en diferentes proveedores de correo electrónico . Si sus correos electrónicos no llegan a la cuenta de Gmail de un usuario, envíe los mismos correos electrónicos a una cuenta de Yahoo, una cuenta de Hotmail y una cuenta POP3 normal (como su cuenta de correo electrónico proporcionada por el ISP).

Si los correos electrónicos llegan a todas o algunas de las otras cuentas de correo electrónico, usted sabe que su código está enviando correos electrónicos, pero es probable que el proveedor de la cuenta de correo electrónico los esté bloqueando por alguna razón. Si el correo electrónico no llega a ninguna cuenta de correo electrónico, es más probable que el problema esté relacionado con su código.

Asegúrese de que el código coincida con el método del formulario

Si ha configurado su método de formulario en POST, asegúrese de que está utilizando $_POSTpara buscar sus valores de formulario. Si lo configuró GETo no lo configuró, asegúrese de usarlo $_GETpara buscar los valores de su formulario.

Asegúrese de que el actionvalor de su formulario apunte a la ubicación correcta

Asegúrese de que su actionatributo de formulario contenga un valor que apunte a su código de correo PHP.

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

Asegúrese de que el proveedor de alojamiento web admita el envío de correo electrónico

Algunos proveedores de alojamiento web no permiten ni habilitan el envío de correos electrónicos a través de sus servidores. Las razones para esto pueden variar, pero si han deshabilitado el envío de correo, deberá utilizar un método alternativo que utilice un tercero para enviarle esos correos electrónicos.

Un correo electrónico a su soporte técnico (después de un viaje a su soporte en línea o preguntas frecuentes) debe aclarar si las capacidades de correo electrónico están disponibles en su servidor.

Asegúrese de que el localhostservidor de correo esté configurado

Si está desarrollando en su estación de trabajo local usando WAMP, MAMP o XAMPP, probablemente no esté instalado un servidor de correo electrónico en su estación de trabajo. Sin uno, PHP no puede enviar correo por defecto.

Puede superar esto instalando un servidor de correo básico. Para Windows puede usar el Mercury Mail gratuito .

También puede usar SMTP para enviar sus correos electrónicos. Vea esta gran respuesta de Vikas Dwivedi para aprender cómo hacer esto.

Habilitar PHP personalizado mail.log

Además del archivo de registro de su MTA y PHP, puede habilitar el registro de la mail()función específicamente. No registra la interacción SMTP completa, sino al menos los parámetros de llamada de función y el script de invocación.

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

Ver http://php.net/manual/en/mail.configuration.php para más detalles. (Es mejor habilitar estas opciones en php.inio .user.inio .htaccessquizás).

Consulte con un servicio de prueba de correo

Hay varios servicios de entrega y verificación de spam que puede utilizar para probar su configuración de MTA / servidor web. Por lo general, envía una sonda de correo a: su dirección, luego obtiene un informe de entrega y más fallas concretas o análisis posteriores:

Use un correo diferente

La mail()función incorporada de PHP es útil y a menudo hace el trabajo, pero tiene sus defectos . Afortunadamente, existen alternativas que ofrecen más potencia y flexibilidad, incluido el manejo de muchos de los problemas descritos anteriormente:

Todo lo cual se puede combinar con un servidor profesional SMTP / proveedor de servicios. (Debido a que los típicos planes de alojamiento web compartido del 15/08 son impredecibles cuando se trata de la configuración / configuración del correo electrónico).


11
Bien escrito, John. Solo agregaría una cosa más: verificar los registros del servidor de correo del servidor de correo remitente (ya sea que esté alojado localmente o remotamente), si es posible, a menudo puede arrojar luz sobre lo que está causando el problema. Estos registros deben mostrar 1) si el servidor de correo emisor recibió o no el mensaje del script PHP y, de ser así, 2) si el MX receptor aceptó o no la entrega del servidor de correo emisor.
mti2935

@ mti2935 Eso es muy útil. Me sorprende que me haya perdido eso. Me aseguraré de agregarlo en breve. :)
John Conde

1
comenzaría con no usar mail(), hace un trabajo tan pobre y es más difícil de depurar que cualquier otra biblioteca de correo

1
el mismo sitio web en 000webhost envía correos electrónicos exitosamente y rápido en el dominio netai.net pero en site88.net tengo el mismo sitio web que obtengo en la consola que el mensaje envía con éxito pero no recibo ningún mensaje. También en el dominio comuf.com obtengo un error. (El mismo sitio web en el mismo host funciona solo en el dominio netai.net, net16.net también funciona)
Nicolas Papaconstantinou

1
mi pregunta ( stackoverflow.com/questions/44866673/… ) se marcó como un duplicado de esta, pero todavía no puedo resolverlo. ¿Alguna sugerencia?
Zachary Elkins

37

Agregue un encabezado de correo en la función de correo:

$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. Siempre intente enviar encabezados en la función de correo.
  2. Si está enviando correo a través de localhost, realice la configuración SMTP para enviar correo.
  3. Si está enviando correo a través de un servidor, compruebe que la función de envío de correo electrónico esté habilitada en su servidor.

20

Si está utilizando una configuración SMTP para enviar su correo electrónico, intente usar PHPMailer en su lugar. Puede descargar la biblioteca desde https://github.com/PHPMailer/PHPMailer .

Creé mi correo electrónico enviando de esta manera:

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
También tuve que usar: require ("phpmailer / class.smtp.php");
Doug

15

Simplemente agregue algunos encabezados antes de enviar el correo:

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

Y una cosa más. La mail()función no funciona en localhost. Sube tu código a un servidor y pruébalo.


1
esto realmente hizo que el formulario se enviara, mi pregunta ahora sería ... ¿cómo muestro el correo electrónico escrito por el usuario, ahora que lo he reemplazado con el encabezado ...
user3818620

¿evitará el correo de la carpeta de spam? He visto que si enviamos más de 10 correos usando este método que usaste en tu código, gmail envía este correo a spam.
jewelhuq

El OP tiene esta línea: $from = 'From: yoursite.com'; que no parece una dirección de correo electrónico válida completa, no hay una parte local. Reemplazó el encabezado From y agregó otros adicionales. O más bien lo $fromanterior es redundante en su ejemplo. Y estar malformado fue probablemente el problema original de los OP.
Progrock

13

Me funcionó en 000webhost haciendo lo siguiente:

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

Ingrese directamente la dirección de correo electrónico cuando envíe el correo electrónico:

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

Uso ''y no "".

Este código funciona, pero el correo electrónico se recibió con un retraso de media hora.


10

En su mayoría, la mail()función está deshabilitada en el alojamiento compartido. Una mejor opción es usar SMTP. La mejor opción sería Gmail o 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();
}
?>

¿Es una buena idea guardar el usuario smtp y la contraseña en texto sin formato en el servidor?
Juri

@Juri probablemente no ... Dios, no puedo entender cómo hacer que la función de correo funcione:. (

9

Si solo usa la mail()función, debe completar el archivo de configuración.

Debe abrir la expansión de correo y configurar el SMTP smtp_portetc., y lo más importante, su nombre de usuario y su contraseña. Sin eso, el correo no puede ser enviado. Además, puede usar la PHPMailclase para enviar.


9

Pruebe estas dos cosas por separado y juntas:

  1. eliminar el if($_POST['submit']){}
  2. quitar $from(solo mi intestino)

8

Creo que esto debería hacer el truco. Acabo de agregar una if(issetconcatenación y agregué a las variables en el cuerpo para separar PHP de 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

Para cualquiera que encuentre esto en el futuro, no recomendaría usarlo mail. Hay algunas respuestas que tocan esto, pero no el por qué .

La mailfunción de PHP no solo es opaca, sino que depende completamente de cualquier MTA que use (es decir, Sendmail ) para hacer el trabajo. mailserá solamente saber si el MTA no pudo aceptarlo (es decir, Sendmail fue abajo cuando intentó enviar). No puede decirle si el correo fue exitoso porque se lo entregó. Como tal (como detalla la respuesta de John Conde ), ahora puedes jugar con los registros de la MTA y esperar que te diga lo suficiente sobre la falla para solucionarlo. Si está en un host compartido o no tiene acceso a los registros de MTA, no tiene suerte. Lamentablemente, el valor predeterminado para la mayoría de las instalaciones de vainilla para Linux lo maneja de esta manera.

Una biblioteca de correo ( PHPMailer , Zend Framework 2+, etc.) hace algo muy diferente mail. Abren un socket directamente al servidor de correo receptor y luego envían los comandos de correo SMTP directamente a través de ese socket. En otras palabras, la clase actúa como su propio MTA (tenga en cuenta que puede indicar a las bibliotecas que utilicen mailpara enviar el correo en última instancia, pero le recomendaría encarecidamente que no lo haga).

Esto significa que puede ver directamente las respuestas del servidor receptor (en PHPMailer, por ejemplo, puede activar la salida de depuración ). No más adivinan si un correo no se pudo enviar o por qué.

Si está utilizando SMTP (es decir, está llamando isSMTP()), puede obtener una transcripción detallada de la conversación SMTP utilizando la SMTPDebugpropiedad.

Establezca esta opción incluyendo una línea como esta en su script:

$mail->SMTPDebug = 2;

También obtienes el beneficio de una mejor interfaz. Con mailusted tiene que configurar todos sus encabezados, archivos adjuntos, etc. Con una biblioteca, tiene una función dedicada para hacerlo. También significa que la función está haciendo todas las partes difíciles (como los encabezados).


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

Puede usar el correo electrónico de configuración de CodeIgniter . Por ejemplo, usando SMTP (forma simple):

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

¡Esto funciona para mi!


1
fsockopen () [function.fsockopen]: php_network_getaddresses: getaddrinfo falló: No se conoce dicho host. - Si encuentro este error, ¿cuál es el motivo y qué hay que hacer?
Choudhury Saadmaan Mahmid

1
"Funciona para mí" es solo información anecdótica, pero realmente no es una gran explicación. La contraseña de puerto y smtp sería engañosa para la mayoría de los usuarios.
mario

¿Qué es el "correo electrónico de configuración" ? Tiene una referencia?
Peter Mortensen el

4

Prueba esto

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

Quizás el problema es la configuración del servidor de correo. Para evitar este tipo de problemas o no tiene que preocuparse por el problema del servidor de correo, le recomiendo que use PHPMailer .

Es un complemento que tiene todo lo necesario para enviar correo, y lo único que debe tener en cuenta es tener habilitado el puerto SMTP (Puerto: 25 y 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 ha reemplazado el puerto 465 por el puerto 587. Este es el puerto de envío de correo predeterminado. Cuando un cliente de correo electrónico o un servidor saliente envía un correo electrónico para que lo enrute un servidor de correo adecuado, siempre debe usar el puerto SMTP 587 como puerto predeterminado. Ver mailgun.com/blog/which-smtp-port-understanding-ports-25-465-587 . Un consejo sabio: ¡No abra los puertos en su computadora si no está completamente consciente de lo que está haciendo!
Daño

3

Asegúrese de tener Sendmail instalado en su servidor.

Si ha verificado su código y verificado que no hay nada malo allí, vaya a / var / mail y verifique si esa carpeta está vacía.

Si está vacío, deberá hacer lo siguiente:

sudo apt-get install sendmail

si estás en un servidor Ubuntu


Eso es demasiado grueso para ser útil. La mera instalación de un MTA rara vez permitirá llegar a él. Y una guía completa de configuración de sendmail / postfix / qmail estaría fuera de tema aquí.
mario

¿Es este comentario en referencia a mi respuesta? Porque esto no me ha sucedido y no lo resolví de la misma manera. Hay varias respuestas posibles a la pregunta, siendo la mía una de ellas después de haber intentado todo lo anterior en el pasado, mi respuesta me resolvió el problema, así que la ofrecí aquí como otra solución potencial.
Daniel

Si seguro. Es una de las muchas respuestas posibles. Sin embargo, todavía es camino a la OMI superficial. Generalizarlo en "necesita un MTA" como ... - y aquí hay algunas guías de configuración vinculadas ... sin embargo, podría ser más práctico.
mario

3

En primer lugar, es posible que tenga demasiados parámetros para la función mail () ... Puede tener un máximo de cinco, mail(to, subject, message, headers, parameters);

En cuanto a la $fromvariable, eso debería provenir automáticamente de su servidor web si está utilizando el cPanel de Linux . Proviene automáticamente de su nombre de usuario y dirección IP de cPanel.

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

También asegúrese de tener el orden correcto de las variables en su función mail ().

En mail($to, $subject, $message, etc.)ese orden, o de lo contrario existe la posibilidad de que no funcione.


3

Si tiene problemas para enviar correos con PHP, considere una alternativa como PHPMailer o SwiftMailer .

Usualmente uso SwiftMailer cuando necesito enviar correos con PHP.


Uso básico:

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

Consulte la documentación oficial para obtener más información sobre cómo usar SwiftMailer.


3

Para aquellos que no quieren usar correos externos y quieren enviar correo () en un servidor Linux dedicado.

La forma, cómo los correos PHP, se describe php.inien la sección[mail function] .

El parámetro sendmail-pathdescribe cómo se llama sendmail. El valor predeterminado es sendmail -t -i, por lo que si funciona sendmail -t -i < message.txten la consola de Linux, habrá terminado. También puede agregar mail.loga la depuración y asegurarse de que realmente se llame a mail ().

Se pueden implementar diferentes MTA sendmail. Simplemente hacen un enlace simbólico a sus binarios en ese nombre. Por ejemplo, en Debian, el valor predeterminado es Postfix . Configure su MTA para enviar correo y pruébelo desde la consola con sendmail -v -t -i < message.txt. El archivo message.txtdebe contener todos los encabezados de un mensaje y un cuerpo, la dirección de destino del sobre se tomará del To:encabezado. Ejemplo:

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

Text body.

Prefiero usar ssmtp como MTA porque es simple y no requiere ejecutar un demonio con puertos abiertos. ssmtp solo sirve para enviar correo desde localhost . También puede enviar correos electrónicos autenticados a través de su cuenta en un servicio de correo público. Instale ssmtp y edite el archivo de configuración /etc/ssmtp/ssmtp.conf. Para poder también recibir correo del sistema local a cuentas Unix (alertas a la raíz de trabajos cron, por ejemplo) configurar/etc/ssmtp/revaliases archivo.

Aquí está mi configuración para mi cuenta en el correo Yandex:

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

2

Esto solo afectará a un pequeño puñado de usuarios, pero me gustaría documentarlo para ese pequeño puñado. Este miembro de ese pequeño puñado pasó 6 horas solucionando problemas de un script de correo PHP que funcionaba debido a este problema.

Si vas a una universidad que ejecuta XAMPP desde www.AceITLab.com, debes saber lo que nuestro profesor no nos dijo: el firewall AceITLab (no el firewall de Windows) bloquea MercuryMail en XAMPP. Tendrá que usar un cliente de correo alternativo, Pear está trabajando para nosotros. Tendrá que enviar a una cuenta de Gmail con una configuración de baja seguridad.

Sí, lo sé, esto es totalmente inútil para el correo electrónico del mundo real. Sin embargo, por lo que he visto, los entornos académicos y el mundo real a menudo tienen muy poco en común.


Eso es demasiado extraño, y de hecho no ayudará a nadie más. Utilice el enlace [eliminar] debajo de su respuesta, por favor.
Mario

¿Qué es "pera" en este contexto? ¿Te refieres a PEAR , el repositorio de software PHP? ¿O algo mas? Por ejemplo, los compañeros ?
Peter Mortensen el

¿Realmente quieres decir "precioso pequeño" ? ¿Es algo que desear? ¿Por qué?
Peter Mortensen el

1

Si está ejecutando este código en un servidor local (es decir, su computadora con fines de desarrollo), no enviará el correo electrónico al destinatario. Creará un .txtarchivo en una carpeta llamadamailoutput .

En el caso de que esté utilizando un servicio de manguera gratuito, como 000webhosto hostinger, esos proveedores de servicios deshabilitan elmail() función para evitar usos no deseados de suplantación de correo electrónico, correo no deseado, etc. Prefiero que se comunique con ellos para ver si admiten esta función.

Si está seguro de que el proveedor de servicios admite la función mail (), puede consultar este manual de PHP para obtener más información,

Correo PHP ()

Para verificar si su servicio de alojamiento admite la función mail (), intente ejecutar este código (recuerde cambiar la dirección de correo electrónico del destinatario) :

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

¡La instalación de Sendmail para Debian 10.0.0 ('Buster') fue de hecho trivial!

php.ini

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

Instalación estándar del paquete sendmail (que permite 'enviar'):

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

Comandos útiles diversos:

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

Verificación (de capacidad de enviar)

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

Lo anterior tomó alrededor de 5 minutos. Luego perdí 5 horas ... ¡No olvides revisar tu carpeta de spam !


0

Hay varias posibilidades:

  1. Estás enfrentando un problema de servidor. El servidor no tiene ningún servidor de correo. Por lo tanto, su correo no funciona, porque su código está bien y el correo funciona con el tipo.

  2. No está obteniendo el valor publicado. Pruebe su código con un valor estático.

  3. Usar correos SMTP para enviar correos ...


0

Puede usar 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

55
Importante mencionar: esto es simplemente un mail()contenedor de funciones. Solo agrega construcción de mensajes y algunos trucos.
Mario

0

Puede ver sus errores al:

error_reporting(E_ALL);

Y mi código de muestra es:

<?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 = 0no es útil Una "contraseña" simple tampoco funcionaría con GMail. Esta respuesta no contribuye mucho aquí.
Mario

-2

Siempre que su sistema sendmail funcione, su código debe modificarse de la siguiente manera:

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

Esto le permite enviar correos electrónicos basados ​​en HTML.

De notable interés:

  1. construimos una cadena de encabezado multilíneas (cada línea separada por \ r \ n);
  2. agregamos Content-type para expresar que devolvemos HTML para que pueda componer mejores correos electrónicos (puede agregar el código HTML que desee, incluido CSS, a su mensaje como lo haría en la página HTML).

Nota: la <<<EOBsintaxis requiere que el último marcador EOB comience como el comienzo de la línea y no tenga espacio ni ningún carácter después del punto y coma.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.