J'ai mail()
de PHP en utilisant ssmtp qui n'a pas de file d'attente/spool et qui est synchrone avec AWS SES.
J'ai entendu dire que je pourrais utiliser SwiftMail pour fournir un spool, mais je ne pouvais pas élaborer une recette simple pour l'utiliser comme je le fais actuellement avec mail()
.
Je veux que le moins de code possible fournisse un courrier asynchrone. Peu m'importe si l'e-mail ne parvient pas à envoyer, mais ce serait bien d'avoir un journal.
Des trucs ou astuces simples? À court d'exécuter un serveur de messagerie complet? Je pensais qu'un wrapper sendmail
pourrait être la solution, mais je ne pouvais pas travailler Nohup
.
Vous devez exécuter php-fpm pour fastcgi_finish_request pour être disponible.
echo "I get output instantly";
fastcgi_finish_request(); // Close and flush the connection.
sleep(10); // For illustrative purposes. Delete me.
mail("[email protected]", "lol", "Hi");
Il est assez facile de mettre en file d'attente n'importe quel code arbitraire à traiter après avoir terminé la requête à l'utilisateur:
$post_processing = [];
/* your code */
$email = "[email protected]";
$subject = "lol";
$message = "Hi";
$post_processing[] = function() use ($email, $subject, $message) {
mail($email, $subject, $message);
};
echo "Stuff is going to happen.";
/* end */
fastcgi_finish_request();
foreach($post_processing as $function) {
$function();
}
Arrêtez instantanément une boucle et laissez la nouvelle demande y répondre. Je faisais cela sur des hôtes partagés avant que ce soit cool. (ce n'est jamais cool)
if(!empty($_POST)) {
sleep(10);
mail($_POST['email'], $_POST['subject'], $_POST['message']);
exit(); // Stop so we don't self DDOS.
}
$ch = curl_init("http://" . $_SERVER['HTTP_Host'] . $_SERVER['REQUEST_URI']);
curl_setopt($ch, CURLOPT_TIMEOUT, 1);
curl_setopt($ch, CURLOPT_NOSIGNAL, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, [
'email' => '[email protected]',
'subject' => 'foo',
'message' => 'bar'
]);
curl_exec($ch);
curl_close($ch);
echo "Expect an email in 10 seconds.";
Vous avez beaucoup de façons de faire cela, mais le traitement du fil n'est pas nécessairement le bon choix.
from
, to
, message
, sent
(booléen défini sur true
lorsque vous avez envoyé l'email). <?php
class MailSpool
{
public static $mails = [];
public static function addMail($subject, $to, $message)
{
self::$mails[] = [ 'subject' => $subject, 'to' => $to, 'message' => $message ];
}
public static function send()
{
foreach(self::$mails as $mail) {
mail($mail['to'], $mail['subject'], $mail['message']);
}
}
}
//In your script you can call anywhere
MailSpool::addMail('Hello', '[email protected]', 'Hello from the spool');
register_shutdown_function('MailSpool::send');
exit(); // You need to call this to send the response immediately
Utilisez AWS SES avec PHPMailer .
Cette méthode est très rapide (des centaines de messages par seconde) et ne nécessite pas beaucoup de code.
$mail = new PHPMailer;
$mail->isSMTP(); // Set mailer to use SMTP
$mail->Host = 'ssl://email-smtp.us-west-2.amazonaws.com'; // Specify main and backup SMTP servers
$mail->SMTPAuth = true; // Enable SMTP authentication
$mail->Username = 'blah'; // SMTP username
$mail->Password = 'blahblah'; // SMTP password
$mail->SMTPSecure = 'tls'; // Enable TLS encryption, `ssl` also accepted
$mail->Port = 443;
Je ne sais pas si j'ai bien interprété votre question, mais j'espère que cela vous aidera.
Pthreads est ton ami :)
Ceci est un exemple de la manière dont j’ai réalisé mon application de production
class AsynchMail extends Thread{
private $_mail_from;
private $_mail_to;
private $_subject;
public function __construct($subject, $mail_to, ...) {
$this->_subject = $subject;
$this->_mail_to = $mail_to;
// ...
}
// ...
// you must redefine run() method, and to execute it we must call start() method
public function run() {
// here put your mail() function
mail($this->_mail_to, ...);
}
}
TEST SCRIPT EXEMPLE
$mail_to_list = array('[email protected]', '[email protected]',...);
foreach($mail_to_list as $mail_to) {
$asynchMail = new AsynchMail($mail_to);
$asynchMail->start();
}
Faites-moi savoir si vous avez besoin d'aide supplémentaire pour l'installation et l'utilisation de threads en PHP
Pour la journalisation, je vous conseille vivement d’utiliser Log4PHP : puissant, facile à utiliser et à configurer
Pour l’envoi de mails, je vous conseille également vivement d’utiliser PHPMailer
J'utilise une exécution PHP asynchrone en utilisant beanstalkd .
Il s’agit d’une simple file de messages, très légère et facile à intégrer.
En utilisant le wrapper php suivant pour php https://github.com/pda/pheanstalk , Vous pouvez procéder de la manière suivante pour implémenter un gestionnaire de messagerie:
use Beanstalk\Client;
$msg="dest_email##email_subject##from_email##email_body";
$beanstalk = new Client();
$beanstalk->connect();
$beanstalk->useTube('flux'); // Begin to use tube `'flux'`.
$beanstalk->put(
23, // Give the job a priority of 23.
0, // Do not wait to put job into the ready queue.
60, // Give the job 1 minute to run.
$msg // job body
);
$beanstalk->disconnect();
Ensuite, le travail serait effectué dans un code placé dans un fichier php séparé.
Quelque chose comme:
use Beanstalk\Client;
$do=true;
try {
$beanstalk = new Client();
$beanstalk->connect();
$beanstalk->watch('flux');
} catch (Exception $e ) {
echo $e->getMessage();
echo $e->getTraceAsString();
$do = false;
}
while ($do) {
$job = $beanstalk->reserve(); // Block until job is available.
$emailParts = explode("##", $job['body'] );
// Use your SendMail function here
if ($i_am_ok) {
$beanstalk->delete($job['id']);
} else {
$beanstalk->bury($job['id'], 20);
}
}
$beanstalk->disconnect();
Vous pouvez exécuter ce fichier php séparément, en tant que processus php indépendant. Disons que vous l'enregistrez sous sender.php, il sera exécuté sous Unix comme:
php /path/to/sender/sender.php & && disown
Cette commande exécute le fichier et vous permet également de fermer la console ou de déconnecter l’utilisateur actuel sans arrêter le processus.
Assurez-vous également que votre serveur Web utilise le même fichier php.ini que votre interpréteur de ligne de commande php. (Peut-être résolu en utilisant un lien vers votre php.ini préféré)
J'espère que ça aide.
Bienvenue sur async PHP https://github.com/shuchkin/react-smtp-client
$loop = \React\EventLoop\Factory::create();
$smtp = new \Shuchkin\ReactSMTP\Client( $loop, 'tls://smtp.google.com:465', '[email protected]','password' );
$smtp->send('[email protected]', '[email protected]', 'Test ReactPHP mailer', 'Hello, Sergey!')->then(
function() {
echo 'Message sent via Google SMTP'.PHP_EOL;
},
function ( \Exception $ex ) {
echo 'SMTP error '.$ex->getCode().' '.$ex->getMessage().PHP_EOL;
}
);
$loop->run();
Votre meilleur pari est avec un motif d'empilement ou de mise en file d'attente. C'est assez simple et peut être décrit en 2 étapes.
Une méthode simple consiste à appeler le code qui traite vos messages de manière asynchrone.
Par exemple, si vous avez un fichier nommé email.php avec le code suivant:
// Example array with e-mailaddresses
$emailaddresses = ['[email protected]', '[email protected]', '[email protected]'];
// Call your mail function
mailer::sendMail($emailaddresses);
Vous pouvez ensuite appeler cela de manière asynchrone dans une requête normale telle que
exec('Nice -n 20 php email.php > /dev/null & echo $!');
Et la demande se terminera sans attendre que email.php ait fini d'envoyer les courriels. La journalisation pourrait également être ajoutée au fichier contenant les courriers électroniques.
Les variables peuvent être passées dans l'exécutable entre le nom de fichier appelé et > /dev/null
comme
exec('Nice -n 20 php email.php '.$var1.' '.$var2.' > /dev/null & echo $!');
Assurez-vous que ces variables sont en sécurité avec escapeshellarg () . Dans le fichier appelé, ces variables peuvent être utilisées avec $ argv