9.4. 发送邮件

现在,我们已经准备好一封邮件了,让我们切实地把它发出去吧。发送一封邮件之前,我们要选择使用哪种传输机制,然后再使用这种机制来发送邮件。

9.4.1. 使用其中一种传输机制

Solar自带了两种Solar_Mail_Transport(邮件传输)适配器:一种是Phpmail适合器,它使用PHP内置的mail()方法;另一种是SMTP工厂适配器,它的使用方法复杂一点点,但是健壮很多。

9.4.1.1. 使用PHP mail()传输

非常简单:基于PHP内置mail()函数的适配器。

<?php
$mail = Solar::factory('Solar_Mail_Message');
// .. build the message ...

// build a transport and send the message
$transport = Solar::factory('Solar_Mail_Transport', array(
    'adapter' => 'Solar_Mail_Transport_Adapter_Phpmail'
));

$transport->send($mail);
?>

使用Solar_Smtp传输

SMTP工厂适配器比之前的Mail适配器复杂一些,但也不是你想象中那么复杂。我们需要建立一个SMTP连接对象,然后告诉SMTP传输适配器使用它,最后发送邮件。

<?php
$mail = Solar::factory('Solar_Mail_Message');
// ...

// build an SMTP connection object
$smtp = Solar::factory('Solar_Smtp', array(
    'adapter' => 'Solar_Smtp_Adapter_NoAuth',
    'host'    => 'mail.example.com',
));

// build a transport and send the message
$transport = Solar::factory('Solar_Mail_Transport', array(
    'adapter' => 'Solar_Mail_Transport_Adapter_Smtp',
    'smtp'    => $smtp,
));

$transport->send($mail);
?>

SMTP连接对象本身就是一个工厂,它包含各种不同的验证适配器:

9.4.2. 传输依赖注入

你无需每次发邮件时都建立一个传输连接对象,你可以为邮件信息配置一个依赖注入的传输连接对象。然后邮件信息就会使用注入的那个传输连接对象发送它自己了。对于Solar_Mail_Message类,配置传输连接对象注入的键名是'transport'。

9.4.2.1. 使用配置数组配置注入

使用依赖注入最简单的方法就是为'transport'传递一个配置数组。这里有一个向邮件消息注入PHPmail()适配器的简单示例:

<?php
// create a message object, and inject a transport config
$mail = Solar::factory('Solar_Mail_Message', array(
    'transport' => array(
        'adapter' => 'Solar_Mail_Transport_Adapter_Phpmail',
    )
));

// ... compose the message ...

// now tell the email to "send itself".
// this uses the injected transport.
$mail->send();
?>

下面有一个稍微复杂点的示例,它使用Solar_Smtp工厂适配器作为传输连接对象,该对象使用纯文本方式验证。注意到,传输连接对象本身也使用依赖注入,通过给'smtp'键传递一个配置数组注入Solar_Smtp对象。

<?php
// create a message object, and inject a transport config
$mail = Solar::factory('Solar_Mail_Message', array(
    'transport' => array(
        'adapter' => 'Solar_Mail_Transport_Adapter_Smtp',
        'smtp' => array(
            'adapter'  => 'Solar_Smtp_Adapter_PlainAuth',
            'username' => 'pmjones',
            'password' => 'secret',
            'host'     => 'mail.example.com',
        ),
    )
));

// ... compose the message ...

// now tell the email to "send itself".
// this uses the injected transport.
$mail->send();
?>

这非常方便,特别是你可以提前在你的配置文件中写好配置数组,当你每次创建Solar_Mail_Message对象时,始终把它们作为默认的配置。在这种情况下,你不再需要在使用时传递完整的配置数组了,使用类名就可以了。

<?php
$config['Solar_Mail_Message'] = array(
    'transport' => 'Solar_Mail_Transport_Adapter_Smtp',
);

$config['Solar_Mail_Transport_Adapter_Smtp'] = array(
    'transport' => 'Solar_Smtp_Adapter_PlainAuth',
);

$config['Solar_Smtp_Adapter_PlainAuth'] = array(
    'adapter'  => 'Solar_Smtp_Adapter_PlainAuth',
    'username' => 'pmjones',
    'password' => 'secret',
    'host'     => 'mail.example.com',
);
?>

使用基于配置文件的方式,而不使用基于逻辑的方式,意味着应用的所有配置都可以放在一个地方。你甚至可以在配置文件中改变适配器,而不需要改变邮件发送的代码,前提是要使用相同的注册表名称。

9.4.2.2. 使用注册表注入

使用配置数组配置注入的唯一问题是:在你每次创建Solar_Mail_Message对象的同时也会创建依赖对象。有时候使用注册表来处理依赖注入会更好,至少不会因为重复创建同一个对象而耗光资源。

你可以在你的入口文件或Solar_Controller_Page::_setup()文件中注册SMTP传输对象,这样你就可以在整个应用中使用它。

<?php
// build a Solar_Smtp object
$smtp = Solar::factory('Solar_Smtp', array(
    'adapter'  => 'Solar_Smtp_Adapter_PlainAuth',
    'username' => 'pmjones',
    'password' => 'secret',
    'host'     => 'mail.example.com',
));

// register it as 'smtp'
Solar_Registry::set('smtp', $smtp);

// build a Solar_Mail_Transport object with the SMTP object injected
$transport = Solar::factory('Solar_Mail_Transport', array(
    'adapter' => 'Solar_Mail_Transport_Adapter_Smtp',
    'smtp'    => 'smtp', // uses the registered 'smtp' object
);

// register the transport as 'mail-transport'
Solar_Registry::set('mail-transport', $transport);
?>

现在,当你创建一个新的邮件消息对象时,你可以告诉它已经存在一个可用的传输对象了,然后直接调用send()方法发送邮件。

<?php
$mail = Solar::factory('Solar_Mail_Message', array(
    'transport' => 'mail-transport',
));

// ... build the message, and then:
$mail->send();
?>

如果你愿意,你可以把发送邮件相关的配置信息都写入到Solar的配置文件中。然后你可以从注册表中延迟加载这些对象,而且它们都会有正确的配置。系统会自动帮你延迟加载那些依赖的对象。

在Solar.config.php文件中:

<?php
// configure SMTP
$config['Solar_Smtp'] = array(
    'adapter'  => 'Solar_Smtp_Adapter_PlainAuth',
    'username' => 'pmjones',
    'password' => 'secret',
    'host'     => 'mail.example.com',
);

// configure mail transport
$config['Solar_Mail_Transport'] = array(
    'adapter' => 'Solar_Mail_Transport_Adapter_Smtp',
    'smtp'    => 'smtp',
);

// tell all mail messages to use the registered 'mail-transport'
$config['Solar_Mail_Message']['transport'] = 'mail-transport';
?>

接着你要做的事情就是在你的入口文件中注册类名(注意是注册类名而不是注册对象):

<?php
Solar_Registry::set('smtp', 'Solar_Smtp');
Solar_Registry::set('mail-transport', 'Solar_Mail_Transport');
?>

。。。上面的代码将会在那些对象第一次被依赖调用时创建它们,并且以后你从注册表获取这些对象时,会重用第一次创建的对象。

现在,你可以非常简单地发送邮件消息了:

<?php
// create and build a message
$mail = Solar::factory('Solar_Mail_Message');
// ...

// send the message; this creates the SMTP and mail-transport objects
// from the config-file settings, and sends the message trough the
// registered transport.
$mail->send();
?>