使用带有 docker-compose 的 phpmailer V6

Using phpmailer V6 with docker-compose

我一直在使用带有独立 LAMP 服务器的 PHPMailer 5.2,它运行良好。然而,在研究了更现代的网络服务器设置方法之后,我尝试了 docker-compose 与 php8 和 apache2.

PHPMailer 也有一个更新版本,我在如何使用更新的 PHPmailer(版本 6.4.1)和 docker-compose 时遇到问题。

我的 docker-compose 配置:

version: "3"

services:
  webserver:
    build:
      context: ./bin/${PHPVERSION}
    container_name: '${COMPOSE_PROJECT_NAME}-${PHPVERSION}'
    restart: 'always'
    ports:
      - "${HOST_MACHINE_UNSECURE_HOST_PORT}:80"
      - "${HOST_MACHINE_SECURE_HOST_PORT}:443"
    links:
      - database
    volumes:
      - ${DOCUMENT_ROOT-./www}:/var/www/html
      - ${PHP_INI-./config/php/php.ini}:/usr/local/etc/php/php.ini
      - ${VHOSTS_DIR-./config/vhosts}:/etc/apache2/sites-enabled
      - ${LOG_DIR-./logs/apache2}:/var/log/apache2
      - ./config/opt:/opt
    environment:
      APACHE_DOCUMENT_ROOT: ${APACHE_DOCUMENT_ROOT-/var/www/html}
      PMA_PORT: ${HOST_MACHINE_PMA_PORT}
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
  database:
    build:
      context: "./bin/${DATABASE}"
    container_name: '${COMPOSE_PROJECT_NAME}-database'
    restart: 'always'
    ports:
      - "127.0.0.1:${HOST_MACHINE_MYSQL_PORT}:3306"
    volumes:
      - ${MYSQL_DATA_DIR-./data/mysql}:/var/lib/mysql
      - ${MYSQL_LOG_DIR-./logs/mysql}:/var/log/mysql
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: ${MYSQL_DATABASE}
      MYSQL_USER: ${MYSQL_USER}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
  phpmyadmin:
    image: phpmyadmin/phpmyadmin
    container_name: '${COMPOSE_PROJECT_NAME}-phpmyadmin'
    links:
      - database
    environment:
      PMA_HOST: database
      PMA_PORT: 3306
      PMA_USER: root
      PMA_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_USER: ${MYSQL_USER}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
    ports:
      - '${HOST_MACHINE_PMA_PORT}:80'
    volumes:
      - /sessions
      - ${PHP_INI-./config/php/php.ini}:/usr/local/etc/php/conf.d/php-phpmyadmin.ini
  redis:
    container_name: '${COMPOSE_PROJECT_NAME}-redis'
    image: redis:latest
    ports:
      - "127.0.0.1:${HOST_MACHINE_REDIS_PORT}:6379"

php 运行良好。现在,根据 PHPMailer 的 documentation,我将包下载为 zip 文件并将其解压缩到包含我的 email.php 文件的文件夹下。

目录结构是,

www
'--php/
'-----/email.php
'-----/PHPMailer-master/
'----------------------/src
'-------------------------/PHPMailer.php
'-------------------------/POP3.php
'-------------------------/SMTP.php
'-------------------------/Exception.php
'-------------------------/OAuth.php

email.php 文件的内容如下:

<?php

//Import PHPMailer classes into the global namespace
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;

//Import the PHPMailer class into the global namespace
require './PHPMailer-master/src/Exception.php';
require './PHPMailer-master/src/PHPMailer.php';
require './PHPMailer-master/src/SMTP.php';


//----------------------------------------
$title='<h2><p style="color:DarkBlue ;">SAMPLE title</h2></p><br>  ';
$msg1='<p style="color:Black ;">sample message </p>';
$sampleTxt=$title.$msg1;

//----------------------------------------
//Create a new PHPMailer instance
$mail = new PHPMailer();
$mail->isSMTP();

//Set the SMTP port number - 587 for authenticated TLS, a.k.a. RFC4409 SMTP submission
$mail->Port = 587;

//Set the encryption mechanism to use - STARTTLS or SMTPS
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;

//Whether to use SMTP authentication
$mail->SMTPAuth = true;

//Username to use for SMTP authentication - use full email address for gmail
$mail->Username = '<my_email_@gmail.com>';

//Password to use for SMTP authentication
$mail->Password = '<my_password>';

//Set PHPMailer to use the sendmail transport
$mail->isSendmail();
//Set who the message is to be sent from
$mail->setFrom('<sendingmail@gmail.com>', 'Name');
//Set an alternative reply-to address
////Set who the message is to be sent to
$mail->addAddress('<receiver@gmail.com>', 'Receiver');
//Set the subject line
$mail->Subject = 'PHPMailer sendmail test';
//Read an HTML message body from an external file, convert referenced images to embedded,
//convert HTML into a basic plain-text alternative body
//$mail->msgHTML(file_get_contents('contents.html'), __DIR__);
$mail->Body = $sampleTxt;
//Replace the plain text body with one created manually
$mail->AltBody = 'This is a plain-text message body';


//send the message, check for errors
if (!$mail->send()) {
    echo 'Mailer Error: ' . $mail->ErrorInfo;
} else {
    echo 'Message sent!';
}

执行 php 文件后,我收到错误:Mailer Error: Could not execute: /usr/sbin/sendmail -t -i

有人可以帮忙吗?谢谢。

PS:

1.) 我在 php 文件中提供了正确的电子邮件地址,我已在此处替换了它。

2.) 我正在尝试使用 Gmail 发送电子邮件。


互联网上的许多例子都提到需要使用,require 'vendor/autoload.php'; 但是我的文件夹或任何文件夹中都没有这个目录include_paths


更新: 尝试将作曲家包含在 docker-compose 实例中,
  composer:
    restart: 'no'
    container_name: composer
    image: "composer"
    command: install
    volumes:
      - ./config/composer:/app

在 config/composer 文件夹中是 composer.json 和

{
    "require": {
        "phpmailer/phpmailer": "^6.2"
    }
}

在 yml 文件中添加了以上行,composer 给出错误,

composer      |   - Installing phpmailer/phpmailer (v6.4.1): Extracting archive
composer      | 5 package suggestions were added by new dependencies, use `composer suggest` to see details.
composer      | Generating autoload files
composer      | 1 package you are using is looking for funding.
composer      | Use the `composer fund` command to find out more!
composer exited with code 0

这已通过使用 docker-compose 安装 composer 解决。以下块已包含在 docker-compose.yml

  composer:
    restart: 'no'
    container_name: composer
    image: "composer"
    command: install --no-suggest
    volumes:
      - ./www/admin/php:/app

上面最后一行定义了 phpmailer 的安装位置。在此文件夹中,我们保留 php 脚本,该脚本将使用 phpmailer.


已安装 php邮件程序

在文件夹 /www/admin/php/ 中,composer 将创建一个文件夹 vendor,其中包含名为 autoloader.php 的脚本以及 phpmailer 源文件。


因此,在文件夹 /www/admin/php/ 中放置了脚本 mail.php,其内容如下。

<?php

//Import PHPMailer classes into the global namespace
//These must be at the top of your script, not inside a function
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception;

//Load Composer's autoloader
require 'vendor/autoload.php';

//-------------------------------------------------------

// this function (for sending email) needs editing the sender's email details
function send_email($receiver, $receiver_name,  $subject, $body_string){

  // SERVER SETTINGS
  $mail = new PHPMailer(true);
  $mail->isSMTP();                                            //Send using SMTP
  $mail->Host       = 'smtp.gmail.com';                     //Set the SMTP server to send through
  $mail->SMTPAuth   = true;                                   //Enable SMTP authentication
  $mail->Username   = '<username at gmail.com>';                     //SMTP username
  $mail->Password   = '<login password>';                               //SMTP password
  $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;         //Enable TLS encryption; `PHPMailer::ENCRYPTION_SMTPS` encouraged
  $mail->Port       = 587;
  //-------------------------------------------

  //Recipients (change this for every project)
  $mail->setFrom('<from address email>', '<name>');
  $mail->addAddress($receiver, $receiver_name);     //Add a recipient
  $mail->addReplyTo('<reply to email address>', '<name>');

  //Content
  $mail->isHTML(true);                                  //Set email format to HTML
  $mail->Subject = $subject;
  $mail->Body    = $body_string;  // html

  //send the message, check for errors
  if (!$mail->send()) {
      //echo 'Mailer Error: ' . $mail->ErrorInfo;
      return 0;
  } else {
      //echo 'Message sent!';
      return 1;
  }
}
//----------------------------------------------------------------------

// set parameters
$subject = 'string';
$body_string = 'Hello,<br><br>Some message.<br> This is an example.';
$receiver='<receiver email>'; 
$receiver_name='<receiver's name>';

// set email
$result = send_email($receiver, $receiver_name,  $subject, $body_string);

?>

这很好用,也适用于 phpmailer documentation and examples.

中给出的示例