Zend\Mail 使用 Gmail 失败,但 SwiftMailer 缺少 development/testing 的文件传输。该怎么办?

Zend\Mail fails with Gmail, but SwiftMailer lacks a file transport for development/testing. what to do?

我已成功使用 ZF1 中的 Zend_Mail 通过 SMTP 连接到 GMail 帐户,但无法使其与 Zend\Mail 一起使用。以下产生了 "Connection timed out" 异常:

use Zend\Mail\Message;
use Zend\Mail\Transport\Smtp as SmtpTransport;
use Zend\Mail\Transport\SmtpOptions;

$transport = new SmtpTransport();
$options   = new SmtpOptions([
    'host' => 'smtp.gmail.com',
    'connection_class' => 'login',
    'connection_config' => [
        'username' => 'my_username@gmail.com',
        'password' => 'redacted',
        'port' => 587,
        'ssl' => 'tls',
    ],
]);
$transport->setOptions($options);
$message = new Message();
$message->addTo('recipient@example.org')
    ->setFrom('me@example.org')
    ->setSubject('hello, fool!')
    ->setBody("testing one two three! time is now ".date('r'));

$transport->send($message);

但是!当我使用 PHP Swiftmailer、Python 以及较旧的 Zend_Mail 执行与上述等效的操作时,相同的连接参数工作正常。所有这些当然都在同一个环境中(我的 Ubuntu 14.04 框)。所以,我认为 Zend\Mail 一定有问题——或者更准确地说 Zend\Mail\Transport\Smtp.

不幸的是,我不是一个英雄(并且缺乏技能)来深入研究 Zend\Mail\Transport\Smtp 并修复它,所以我转向了 Swiftmailer (http://swiftmailer.org/)。而且效果很好,

$transport = Swift_SmtpTransport::newInstance('smtp.gmail.com', 587, 'tls');
$transport->setUsername('my_username@gmail.com')
->setPassword('redacted');
$mailer = Swift_Mailer::newInstance($transport);
$message = Swift_Message::newInstance();

$message->setSubject("testing from Swiftmailer")
    ->setFrom("me@example.org")
    ->setTo('recipient@example.org')
    ->setBody("yadda yadda blah blah blah!");
$result = $mailer->send($message); // nice and easy!

但缺少一个不错的功能:Zend\Mail 有一个文件传输功能,可以将您的消息简单地转储到一个文件中,当您真的不想向任何人发送电子邮件消息时,这对于开发和测试来说非常方便。

怎么办?我熟悉将 "environment" 环境变量设置为 "development"、"production" 等的配置技巧,并让我的代码决定如何相应地配置自身。但到目前为止,在我的思想实验中,这有点尴尬。

一个想法:继承 Swift_Mailer 并覆盖 send() 以简单地将消息写入磁盘,并参考 $environment 来决定是实例化真实的东西还是不真正实例化的子类发送。

但我很想听听其他一些想法和建议。

好的,这是一个 two-part 的答案,您可以选择。

答案 #1:不用担心写入文件,只需使用 Swiftmailer 的未记录 Swift_NullTransport 就像这样:

$transport = new Swift_NullTransport::newInstance();
/* and so forth */

Swift_Transport_NullTransport(Swift_NullTransport 的父级)的 send() 方法什么都不做,就好像它成功了一样,在我的例子中,这与转储到文件一样好。

答案 #2:以某种方式推出自己的,例如,(a) 通过扩展其中一个传输 类 并覆盖 send(),或者 (b) 编写另一个传输 send() 写入文件,然后在 Github 上发布 PR 以利益所有有情众生。

对于 swiftmailer,您可以使用带 FileSpool 的 SpoolTransport 将消息存储到文件系统。 Example(铃木纪夫):

/**
 * 270-transport-spool-file.php
 */
require_once '../vendor/autoload.php';
require_once './config.php';
// POINT of this sample
$path = FILE_SPOOL_PATH;
$spool = new Swift_FileSpool($path);
$transport = Swift_SpoolTransport::newInstance($spool);
$mailer = Swift_Mailer::newInstance($transport);
$message = Swift_Message::newInstance();
$message
    ->setFrom(MAIL_FROM)
    ->setTo(MAIL_TO)
    ->setSubject('SpoolTransport (file) sample')
    ->setBody('This is a mail.')
;
// Serialized Swift_Message objects were spooled to $path
$result = $mailer->send($message);